From 2326f42ce2529330ffbd1b865b90338bd4bf17fd Mon Sep 17 00:00:00 2001 From: Dylan DPC Date: Tue, 25 Oct 2022 18:07:21 +0530 Subject: [PATCH 001/676] stabilise array methods --- library/alloc/src/lib.rs | 1 - library/core/src/array/mod.rs | 9 ++------- library/core/tests/lib.rs | 1 - src/librustdoc/lib.rs | 1 - 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index ce36b116f139b..a222871a84650 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -92,7 +92,6 @@ #![feature(allocator_api)] #![feature(array_chunks)] #![feature(array_into_iter_constructors)] -#![feature(array_methods)] #![feature(array_windows)] #![feature(assert_matches)] #![feature(async_iterator)] diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index eae0e1c761866..5fbf15f1a28ba 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -592,8 +592,6 @@ impl [T; N] { /// # Example /// /// ``` - /// #![feature(array_methods)] - /// /// let floats = [3.1, 2.7, -1.0]; /// let float_refs: [&f64; 3] = floats.each_ref(); /// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]); @@ -604,8 +602,6 @@ impl [T; N] { /// array if its elements are not [`Copy`]. /// /// ``` - /// #![feature(array_methods)] - /// /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()]; /// let is_ascii = strings.each_ref().map(|s| s.is_ascii()); /// assert_eq!(is_ascii, [true, false, true]); @@ -613,7 +609,7 @@ impl [T; N] { /// // We can still access the original array: it has not been moved. /// assert_eq!(strings.len(), 3); /// ``` - #[unstable(feature = "array_methods", issue = "76118")] + #[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")] pub fn each_ref(&self) -> [&T; N] { // SAFETY: we know for certain that this iterator will yield exactly `N` // items. @@ -627,7 +623,6 @@ impl [T; N] { /// # Example /// /// ``` - /// #![feature(array_methods)] /// /// let mut floats = [3.1, 2.7, -1.0]; /// let float_refs: [&mut f64; 3] = floats.each_mut(); @@ -635,7 +630,7 @@ impl [T; N] { /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]); /// assert_eq!(floats, [0.0, 2.7, -1.0]); /// ``` - #[unstable(feature = "array_methods", issue = "76118")] + #[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")] pub fn each_mut(&mut self) -> [&mut T; N] { // SAFETY: we know for certain that this iterator will yield exactly `N` // items. diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 3012a78b9c98e..dda8d27605b7e 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,6 +1,5 @@ #![feature(alloc_layout_extra)] #![feature(array_chunks)] -#![feature(array_methods)] #![feature(array_windows)] #![feature(bigint_helper_methods)] #![feature(cell_update)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 793061a9f7a06..f6b065505530c 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -3,7 +3,6 @@ html_playground_url = "https://play.rust-lang.org/" )] #![feature(rustc_private)] -#![feature(array_methods)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(control_flow_enum)] From bab8d29887a0d801fe72f922dafe75a635bc9198 Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Sat, 8 Jul 2023 19:55:33 +0200 Subject: [PATCH 002/676] impl `From<&[T; N]>` for `Cow<[T]>` --- library/alloc/src/vec/cow.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index 2c799605b7b67..7d2462ee32e0c 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -15,6 +15,19 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { } } +#[unstable(feature = "cow_from_array_ref", issue = "none")] +impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> { + /// Creates a [`Borrowed`] variant of [`Cow`] + /// from a reference to an array. + /// + /// This conversion does not allocate or clone the data. + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed + fn from(s: &'a [T; N]) -> Cow<'a, [T]> { + Cow::Borrowed(s as &[_]) + } +} + #[stable(feature = "cow_from_vec", since = "1.8.0")] impl<'a, T: Clone> From> for Cow<'a, [T]> { /// Creates an [`Owned`] variant of [`Cow`] From 6bfad315265cc36d461dedf19f64e445c872da0c Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Sat, 8 Jul 2023 20:11:47 +0200 Subject: [PATCH 003/676] mark as stable --- library/alloc/src/vec/cow.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index 7d2462ee32e0c..b12910f3690b5 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -15,7 +15,7 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { } } -#[unstable(feature = "cow_from_array_ref", issue = "none")] +#[stable(feature = "cow_from_array_ref", since = "CURRENT_RUSTC_VERSION")] impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> { /// Creates a [`Borrowed`] variant of [`Cow`] /// from a reference to an array. From fbaa7fc85e1462b9fd8ca6c091327f765a9f4821 Mon Sep 17 00:00:00 2001 From: WiktorPrzetacznik Date: Tue, 18 Jul 2023 17:42:28 +0200 Subject: [PATCH 004/676] 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 005/676] 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 006/676] 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 a20866254c6864e49814d6abd47a37fd01bcff0a Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Thu, 12 Oct 2023 15:35:03 -0700 Subject: [PATCH 007/676] References refer to allocated objects --- library/core/src/primitive_docs.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 380a21b376bde..e73d5f990cbac 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1389,6 +1389,18 @@ mod prim_usize {} /// work on references as well as they do on owned values! The implementations described here are /// meant for generic contexts, where the final type `T` is a type parameter or otherwise not /// locally known. +/// +/// # Safety +/// +/// For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, unsafe code may assume that +/// the following properties hold. It is undefined behavior to produce a `t: &T` or `t: &mut T` +/// which violates any of these properties. +/// +/// * `t` is aligned to `align_of_val(t)` +/// * `t` refers to a valid instance of `T` +/// * `t` refers to a single [allocated object] +/// +/// [allocated object]: ptr#allocated-object #[stable(feature = "rust1", since = "1.0.0")] mod prim_ref {} From 4f0192a756f756db6bd1c25a8dbe6e89f0086661 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Thu, 12 Oct 2023 18:55:45 -0700 Subject: [PATCH 008/676] Update primitive_docs.rs --- library/core/src/primitive_docs.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index e73d5f990cbac..04ae8c223f2cb 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1397,7 +1397,6 @@ mod prim_usize {} /// which violates any of these properties. /// /// * `t` is aligned to `align_of_val(t)` -/// * `t` refers to a valid instance of `T` /// * `t` refers to a single [allocated object] /// /// [allocated object]: ptr#allocated-object From 39660c4a77d3dda7f5d57a8d91faa946fff5192b Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Fri, 13 Oct 2023 09:47:39 -0700 Subject: [PATCH 009/676] Update library/core/src/primitive_docs.rs Co-authored-by: Ralf Jung --- library/core/src/primitive_docs.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 04ae8c223f2cb..cde49aeb687f0 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1397,7 +1397,11 @@ mod prim_usize {} /// which violates any of these properties. /// /// * `t` is aligned to `align_of_val(t)` -/// * `t` refers to a single [allocated object] +/// * `t` is dereferenceable for `size_of_val(t)` many bytes +/// +/// Being "dereferenceable" for N bytes means that the memory range beginning +/// at the address `t` points to and ending N bytes later is all contained within a +/// single [allocated object]. /// /// [allocated object]: ptr#allocated-object #[stable(feature = "rust1", since = "1.0.0")] From 55487e235b106088ced4e5b4710fa8f9674baaf9 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Fri, 13 Oct 2023 09:49:23 -0700 Subject: [PATCH 010/676] Update primitive_docs.rs --- library/core/src/primitive_docs.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index cde49aeb687f0..19ff41697d9fc 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1399,9 +1399,8 @@ mod prim_usize {} /// * `t` is aligned to `align_of_val(t)` /// * `t` is dereferenceable for `size_of_val(t)` many bytes /// -/// Being "dereferenceable" for N bytes means that the memory range beginning -/// at the address `t` points to and ending N bytes later is all contained within a -/// single [allocated object]. +/// If `t` points at address `a`, being "dereferenceable" for N bytes means that the memory range +/// `[a, a + N)` is all contained within a single [allocated object]. /// /// [allocated object]: ptr#allocated-object #[stable(feature = "rust1", since = "1.0.0")] From 42b1406d9e0be812b1faeefcdd7c61fd788e1043 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Mon, 30 Oct 2023 21:16:23 -0400 Subject: [PATCH 011/676] Make `allow_internal_unstable` work with `stmt_expr_attributes` --- compiler/rustc_expand/src/config.rs | 4 +++- tests/ui/internal/internal-unstable.rs | 10 ++++++++++ tests/ui/internal/internal-unstable.stderr | 8 ++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index bef48765937f5..438796218d449 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -449,7 +449,9 @@ impl<'a> StripUnconfigured<'a> { /// If attributes are not allowed on expressions, emit an error for `attr` #[instrument(level = "trace", skip(self))] pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { - if self.features.is_some_and(|features| !features.stmt_expr_attributes) { + if self.features.is_some_and(|features| !features.stmt_expr_attributes) + && !attr.span.allows_unstable(sym::stmt_expr_attributes) + { let mut err = feature_err( &self.sess.parse_sess, sym::stmt_expr_attributes, diff --git a/tests/ui/internal/internal-unstable.rs b/tests/ui/internal/internal-unstable.rs index 1eb27fbdc3a63..a4445fefef57d 100644 --- a/tests/ui/internal/internal-unstable.rs +++ b/tests/ui/internal/internal-unstable.rs @@ -28,6 +28,14 @@ macro_rules! bar { }} } +#[allow_internal_unstable(stmt_expr_attributes)] +macro_rules! internal_attr { + ($e: expr) => { + #[allow(overflowing_literals)] + $e + } +} + fn main() { // ok, the instability is contained. call_unstable_allow!(); @@ -51,4 +59,6 @@ fn main() { #[allow_internal_unstable] _ => {} } + + assert_eq!(internal_attr!(1e100_f32), f32::INFINITY); } diff --git a/tests/ui/internal/internal-unstable.stderr b/tests/ui/internal/internal-unstable.stderr index b7c47365c2d27..cf741505fa42f 100644 --- a/tests/ui/internal/internal-unstable.stderr +++ b/tests/ui/internal/internal-unstable.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature 'function' - --> $DIR/internal-unstable.rs:40:25 + --> $DIR/internal-unstable.rs:48:25 | LL | pass_through_allow!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | pass_through_allow!(internal_unstable::unstable()); = help: add `#![feature(function)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'function' - --> $DIR/internal-unstable.rs:42:27 + --> $DIR/internal-unstable.rs:50:27 | LL | pass_through_noallow!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | pass_through_noallow!(internal_unstable::unstable()); = help: add `#![feature(function)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'function' - --> $DIR/internal-unstable.rs:46:22 + --> $DIR/internal-unstable.rs:54:22 | LL | println!("{:?}", internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | println!("{:?}", internal_unstable::unstable()); = help: add `#![feature(function)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'function' - --> $DIR/internal-unstable.rs:48:10 + --> $DIR/internal-unstable.rs:56:10 | LL | bar!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 1a0309afb62b01002c1ac2466a6af0dc69594596 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Fri, 3 Nov 2023 06:41:23 -0700 Subject: [PATCH 012/676] Update primitive_docs.rs --- library/core/src/primitive_docs.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 19ff41697d9fc..939342c4d9760 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1393,8 +1393,9 @@ mod prim_usize {} /// # Safety /// /// For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, unsafe code may assume that -/// the following properties hold. It is undefined behavior to produce a `t: &T` or `t: &mut T` -/// which violates any of these properties. +/// the following properties hold. Rust programmers must assume that, unless explicitly stated +/// otherwise, any Rust code they did not author themselves may rely on these properties, and that +/// violating them may cause that code to exhibit undefined behavior. /// /// * `t` is aligned to `align_of_val(t)` /// * `t` is dereferenceable for `size_of_val(t)` many bytes From 8c79f7840d399e3de52c63b1951a46adf6dda515 Mon Sep 17 00:00:00 2001 From: dswij Date: Tue, 7 Nov 2023 17:57:31 +0800 Subject: [PATCH 013/676] `read_zero_byte_vec` refactor for better heuristics --- clippy_lints/src/read_zero_byte_vec.rs | 118 +++++++++++++++---------- tests/ui/read_zero_byte_vec.rs | 29 ++++-- tests/ui/read_zero_byte_vec.stderr | 34 ++++--- 3 files changed, 112 insertions(+), 69 deletions(-) diff --git a/clippy_lints/src/read_zero_byte_vec.rs b/clippy_lints/src/read_zero_byte_vec.rs index b27d4cc6e4f8c..f5a8287d2e09f 100644 --- a/clippy_lints/src/read_zero_byte_vec.rs +++ b/clippy_lints/src/read_zero_byte_vec.rs @@ -1,11 +1,13 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::get_enclosing_block; use clippy_utils::higher::{get_vec_init_kind, VecInitKind}; use clippy_utils::source::snippet; -use clippy_utils::visitors::for_each_expr; -use core::ops::ControlFlow; -use hir::{Expr, ExprKind, Local, PatKind, PathSegment, QPath, StmtKind}; + +use hir::{Expr, ExprKind, HirId, Local, PatKind, PathSegment, QPath, StmtKind}; use rustc_errors::Applicability; use rustc_hir as hir; +use rustc_hir::def::Res; +use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -49,57 +51,40 @@ declare_lint_pass!(ReadZeroByteVec => [READ_ZERO_BYTE_VEC]); impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &hir::Block<'tcx>) { - for (idx, stmt) in block.stmts.iter().enumerate() { - if !stmt.span.from_expansion() - // matches `let v = Vec::new();` - && let StmtKind::Local(local) = stmt.kind - && let Local { pat, init: Some(init), .. } = local - && let PatKind::Binding(_, _, ident, _) = pat.kind + for stmt in block.stmts { + if stmt.span.from_expansion() { + return; + } + + if let StmtKind::Local(local) = stmt.kind + && let Local { + pat, init: Some(init), .. + } = local + && let PatKind::Binding(_, id, ident, _) = pat.kind && let Some(vec_init_kind) = get_vec_init_kind(cx, init) { - let visitor = |expr: &Expr<'_>| { - if let ExprKind::MethodCall(path, _, [arg], _) = expr.kind - && let PathSegment { - ident: read_or_read_exact, - .. - } = *path - && matches!(read_or_read_exact.as_str(), "read" | "read_exact") - && let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind - && let ExprKind::Path(QPath::Resolved(None, inner_path)) = inner.kind - && let [inner_seg] = inner_path.segments - && ident.name == inner_seg.ident.name - { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(()) - } + let mut visitor = ReadVecVisitor { + local_id: id, + read_zero_expr: None, + has_resize: false, }; - let (read_found, next_stmt_span) = if let Some(next_stmt) = block.stmts.get(idx + 1) { - // case { .. stmt; stmt; .. } - (for_each_expr(next_stmt, visitor).is_some(), next_stmt.span) - } else if let Some(e) = block.expr { - // case { .. stmt; expr } - (for_each_expr(e, visitor).is_some(), e.span) - } else { + let Some(enclosing_block) = get_enclosing_block(cx, id) else { return; }; + visitor.visit_block(enclosing_block); - if read_found && !next_stmt_span.from_expansion() { + if let Some(expr) = visitor.read_zero_expr { let applicability = Applicability::MaybeIncorrect; match vec_init_kind { VecInitKind::WithConstCapacity(len) => { span_lint_and_sugg( cx, READ_ZERO_BYTE_VEC, - next_stmt_span, + expr.span, "reading zero byte data to `Vec`", "try", - format!( - "{}.resize({len}, 0); {}", - ident.as_str(), - snippet(cx, next_stmt_span, "..") - ), + format!("{}.resize({len}, 0); {}", ident.as_str(), snippet(cx, expr.span, "..")), applicability, ); }, @@ -108,25 +93,20 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { span_lint_and_sugg( cx, READ_ZERO_BYTE_VEC, - next_stmt_span, + expr.span, "reading zero byte data to `Vec`", "try", format!( "{}.resize({}, 0); {}", ident.as_str(), snippet(cx, e.span, ".."), - snippet(cx, next_stmt_span, "..") + snippet(cx, expr.span, "..") ), applicability, ); }, _ => { - span_lint( - cx, - READ_ZERO_BYTE_VEC, - next_stmt_span, - "reading zero byte data to `Vec`", - ); + span_lint(cx, READ_ZERO_BYTE_VEC, expr.span, "reading zero byte data to `Vec`"); }, } } @@ -134,3 +114,47 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { } } } + +struct ReadVecVisitor<'tcx> { + local_id: HirId, + read_zero_expr: Option<&'tcx Expr<'tcx>>, + has_resize: bool, +} + +impl<'tcx> Visitor<'tcx> for ReadVecVisitor<'tcx> { + fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) { + if let ExprKind::MethodCall(path, receiver, args, _) = e.kind { + let PathSegment { ident, .. } = *path; + + match ident.as_str() { + "read" | "read_exact" => { + let [arg] = args else { return }; + if let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind + && let ExprKind::Path(QPath::Resolved(None, inner_path)) = inner.kind + && let [inner_seg] = inner_path.segments + && let Res::Local(res_id) = inner_seg.res + && self.local_id == res_id + { + self.read_zero_expr = Some(e); + return; + } + }, + "resize" => { + // If the Vec is resized, then it's a valid read + if let ExprKind::Path(QPath::Resolved(_, inner_path)) = receiver.kind + && let Res::Local(res_id) = inner_path.res + && self.local_id == res_id + { + self.has_resize = true; + return; + } + }, + _ => {}, + } + } + + if !self.has_resize && self.read_zero_expr.is_none() { + walk_expr(self, e); + } + } +} diff --git a/tests/ui/read_zero_byte_vec.rs b/tests/ui/read_zero_byte_vec.rs index 76b9b98185119..fd5a88a37a66c 100644 --- a/tests/ui/read_zero_byte_vec.rs +++ b/tests/ui/read_zero_byte_vec.rs @@ -55,14 +55,6 @@ fn test() -> io::Result<()> { let mut buf = [0u8; 100]; f.read(&mut buf)?; - // should not lint - let mut empty = vec![]; - let mut data7 = vec![]; - f.read(&mut empty); - - // should not lint - f.read(&mut data7); - // should not lint let mut data8 = Vec::new(); data8.resize(100, 0); @@ -75,6 +67,27 @@ fn test() -> io::Result<()> { Ok(()) } +fn test_nested() -> io::Result<()> { + let cap = 1000; + let mut f = File::open("foo.txt").unwrap(); + + // Issue #9274 + // Should not lint + let mut v = Vec::new(); + { + v.resize(10, 0); + f.read(&mut v)?; + } + + let mut v = Vec::new(); + { + f.read(&mut v)?; + //~^ ERROR: reading zero byte data to `Vec` + } + + Ok(()) +} + async fn test_futures(r: &mut R) { // should lint let mut data = Vec::new(); diff --git a/tests/ui/read_zero_byte_vec.stderr b/tests/ui/read_zero_byte_vec.stderr index 523ecb2948df3..e85aa051c34bc 100644 --- a/tests/ui/read_zero_byte_vec.stderr +++ b/tests/ui/read_zero_byte_vec.stderr @@ -2,7 +2,7 @@ error: reading zero byte data to `Vec` --> $DIR/read_zero_byte_vec.rs:21:5 | LL | f.read_exact(&mut data).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data.resize(20, 0); f.read_exact(&mut data).unwrap();` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data.resize(20, 0); f.read_exact(&mut data)` | = note: `-D clippy::read-zero-byte-vec` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::read_zero_byte_vec)]` @@ -11,19 +11,19 @@ error: reading zero byte data to `Vec` --> $DIR/read_zero_byte_vec.rs:27:5 | LL | f.read_exact(&mut data2)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data2.resize(cap, 0); f.read_exact(&mut data2)?;` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data2.resize(cap, 0); f.read_exact(&mut data2)` error: reading zero byte data to `Vec` --> $DIR/read_zero_byte_vec.rs:32:5 | LL | f.read_exact(&mut data3)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> $DIR/read_zero_byte_vec.rs:37:5 + --> $DIR/read_zero_byte_vec.rs:37:13 | LL | let _ = f.read(&mut data4)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` --> $DIR/read_zero_byte_vec.rs:43:9 @@ -38,28 +38,34 @@ LL | f.read(&mut data6) | ^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> $DIR/read_zero_byte_vec.rs:81:5 + --> $DIR/read_zero_byte_vec.rs:84:9 + | +LL | f.read(&mut v)?; + | ^^^^^^^^^^^^^^ + +error: reading zero byte data to `Vec` + --> $DIR/read_zero_byte_vec.rs:94:5 | LL | r.read(&mut data).await.unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> $DIR/read_zero_byte_vec.rs:86:5 + --> $DIR/read_zero_byte_vec.rs:99:5 | LL | r.read_exact(&mut data2).await.unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> $DIR/read_zero_byte_vec.rs:93:5 + --> $DIR/read_zero_byte_vec.rs:106:5 | LL | r.read(&mut data).await.unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> $DIR/read_zero_byte_vec.rs:98:5 + --> $DIR/read_zero_byte_vec.rs:111:5 | LL | r.read_exact(&mut data2).await.unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors From 0bccdb34a20643ae1bd07ee6f3f0156640a12120 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Tue, 7 Nov 2023 17:46:00 +0100 Subject: [PATCH 014/676] Stabilize `slice_group_by` Renamed "group by" to "chunk by" a per #80552. Newly stable items: * `core::slice::ChunkBy` * `core::slice::ChunkByMut` * `[T]::chunk` * `[T]::chunk_by` Closes #80552. --- library/alloc/src/lib.rs | 1 - library/alloc/src/slice.rs | 4 +-- library/alloc/tests/lib.rs | 1 - library/alloc/tests/slice.rs | 16 ++++----- library/core/src/slice/iter.rs | 64 +++++++++++++++++----------------- library/core/src/slice/mod.rs | 32 +++++++---------- library/core/tests/lib.rs | 1 - 7 files changed, 54 insertions(+), 65 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 02ecbe22b3e15..7d04a2964037f 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -149,7 +149,6 @@ #![feature(set_ptr_value)] #![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] -#![feature(slice_group_by)] #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] #![feature(slice_range)] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index aa3b7b7e1914b..4033f4eb068c6 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -51,14 +51,14 @@ pub use core::slice::{from_mut, from_ref}; pub use core::slice::{from_mut_ptr_range, from_ptr_range}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{from_raw_parts, from_raw_parts_mut}; +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +pub use core::slice::{ChunkBy, ChunkByMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{Chunks, Windows}; #[stable(feature = "chunks_exact", since = "1.31.0")] pub use core::slice::{ChunksExact, ChunksExactMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{ChunksMut, Split, SplitMut}; -#[unstable(feature = "slice_group_by", issue = "80552")] -pub use core::slice::{GroupBy, GroupByMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{Iter, IterMut}; #[stable(feature = "rchunks", since = "1.31.0")] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 2dcfc6b4abfe9..ca17dab55b027 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -29,7 +29,6 @@ #![feature(iter_advance_by)] #![feature(iter_next_chunk)] #![feature(round_char_boundary)] -#![feature(slice_group_by)] #![feature(slice_partition_dedup)] #![feature(string_remove_matches)] #![feature(const_btree_len)] diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index 784839a3ffa42..c0f7a11a93e12 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -1614,10 +1614,10 @@ fn subslice_patterns() { } #[test] -fn test_group_by() { +fn test_chunk_by() { let slice = &[1, 1, 1, 3, 3, 2, 2, 2, 1, 0]; - let mut iter = slice.group_by(|a, b| a == b); + let mut iter = slice.chunk_by(|a, b| a == b); assert_eq!(iter.next(), Some(&[1, 1, 1][..])); assert_eq!(iter.next(), Some(&[3, 3][..])); assert_eq!(iter.next(), Some(&[2, 2, 2][..])); @@ -1625,7 +1625,7 @@ fn test_group_by() { assert_eq!(iter.next(), Some(&[0][..])); assert_eq!(iter.next(), None); - let mut iter = slice.group_by(|a, b| a == b); + let mut iter = slice.chunk_by(|a, b| a == b); assert_eq!(iter.next_back(), Some(&[0][..])); assert_eq!(iter.next_back(), Some(&[1][..])); assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); @@ -1633,7 +1633,7 @@ fn test_group_by() { assert_eq!(iter.next_back(), Some(&[1, 1, 1][..])); assert_eq!(iter.next_back(), None); - let mut iter = slice.group_by(|a, b| a == b); + let mut iter = slice.chunk_by(|a, b| a == b); assert_eq!(iter.next(), Some(&[1, 1, 1][..])); assert_eq!(iter.next_back(), Some(&[0][..])); assert_eq!(iter.next(), Some(&[3, 3][..])); @@ -1643,10 +1643,10 @@ fn test_group_by() { } #[test] -fn test_group_by_mut() { +fn test_chunk_by_mut() { let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2, 1, 0]; - let mut iter = slice.group_by_mut(|a, b| a == b); + let mut iter = slice.chunk_by_mut(|a, b| a == b); assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); assert_eq!(iter.next(), Some(&mut [3, 3][..])); assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); @@ -1654,7 +1654,7 @@ fn test_group_by_mut() { assert_eq!(iter.next(), Some(&mut [0][..])); assert_eq!(iter.next(), None); - let mut iter = slice.group_by_mut(|a, b| a == b); + let mut iter = slice.chunk_by_mut(|a, b| a == b); assert_eq!(iter.next_back(), Some(&mut [0][..])); assert_eq!(iter.next_back(), Some(&mut [1][..])); assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..])); @@ -1662,7 +1662,7 @@ fn test_group_by_mut() { assert_eq!(iter.next_back(), Some(&mut [1, 1, 1][..])); assert_eq!(iter.next_back(), None); - let mut iter = slice.group_by_mut(|a, b| a == b); + let mut iter = slice.chunk_by_mut(|a, b| a == b); assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); assert_eq!(iter.next_back(), Some(&mut [0][..])); assert_eq!(iter.next(), Some(&mut [3, 3][..])); diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 1c65475b81d70..2d4c7e78aea17 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -3248,26 +3248,26 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMut<'a, T> { /// An iterator over slice in (non-overlapping) chunks separated by a predicate. /// -/// This struct is created by the [`group_by`] method on [slices]. +/// This struct is created by the [`chunk_by`] method on [slices]. /// -/// [`group_by`]: slice::group_by +/// [`chunk_by`]: slice::chunk_by /// [slices]: slice -#[unstable(feature = "slice_group_by", issue = "80552")] +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] #[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct GroupBy<'a, T: 'a, P> { +pub struct ChunkBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a, P> GroupBy<'a, T, P> { +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a, P> ChunkBy<'a, T, P> { pub(super) fn new(slice: &'a [T], predicate: P) -> Self { - GroupBy { slice, predicate } + ChunkBy { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P> +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a, P> Iterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3300,8 +3300,8 @@ where } } -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P> +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a, P> DoubleEndedIterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3322,39 +3322,39 @@ where } } -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a, P> FusedIterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> { +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkBy<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("GroupBy").field("slice", &self.slice).finish() + f.debug_struct("ChunkBy").field("slice", &self.slice).finish() } } /// An iterator over slice in (non-overlapping) mutable chunks separated /// by a predicate. /// -/// This struct is created by the [`group_by_mut`] method on [slices]. +/// This struct is created by the [`chunk_by_mut`] method on [slices]. /// -/// [`group_by_mut`]: slice::group_by_mut +/// [`chunk_by_mut`]: slice::chunk_by_mut /// [slices]: slice -#[unstable(feature = "slice_group_by", issue = "80552")] +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] #[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct GroupByMut<'a, T: 'a, P> { +pub struct ChunkByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a, P> GroupByMut<'a, T, P> { +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a, P> ChunkByMut<'a, T, P> { pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { - GroupByMut { slice, predicate } + ChunkByMut { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P> +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a, P> Iterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3388,8 +3388,8 @@ where } } -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P> +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a, P> DoubleEndedIterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3411,12 +3411,12 @@ where } } -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a, P> FusedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a, P> FusedIterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[unstable(feature = "slice_group_by", issue = "80552")] -impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupByMut<'a, T, P> { +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkByMut<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("GroupByMut").field("slice", &self.slice).finish() + f.debug_struct("ChunkByMut").field("slice", &self.slice).finish() } } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 27dda478848c0..fe18c31df1a8d 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -68,8 +68,8 @@ pub use iter::{ArrayChunks, ArrayChunksMut}; #[unstable(feature = "array_windows", issue = "75027")] pub use iter::ArrayWindows; -#[unstable(feature = "slice_group_by", issue = "80552")] -pub use iter::{GroupBy, GroupByMut}; +#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +pub use iter::{ChunkBy, ChunkByMut}; #[stable(feature = "split_inclusive", since = "1.51.0")] pub use iter::{SplitInclusive, SplitInclusiveMut}; @@ -1755,11 +1755,9 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_group_by)] - /// /// let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; /// - /// let mut iter = slice.group_by(|a, b| a == b); + /// let mut iter = slice.chunk_by(|a, b| a == b); /// /// assert_eq!(iter.next(), Some(&[1, 1, 1][..])); /// assert_eq!(iter.next(), Some(&[3, 3][..])); @@ -1770,24 +1768,22 @@ impl [T] { /// This method can be used to extract the sorted subslices: /// /// ``` - /// #![feature(slice_group_by)] - /// /// let slice = &[1, 1, 2, 3, 2, 3, 2, 3, 4]; /// - /// let mut iter = slice.group_by(|a, b| a <= b); + /// let mut iter = slice.chunk_by(|a, b| a <= b); /// /// assert_eq!(iter.next(), Some(&[1, 1, 2, 3][..])); /// assert_eq!(iter.next(), Some(&[2, 3][..])); /// assert_eq!(iter.next(), Some(&[2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "80552")] + #[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] #[inline] - pub fn group_by(&self, pred: F) -> GroupBy<'_, T, F> + pub fn chunk_by(&self, pred: F) -> ChunkBy<'_, T, F> where F: FnMut(&T, &T) -> bool, { - GroupBy::new(self, pred) + ChunkBy::new(self, pred) } /// Returns an iterator over the slice producing non-overlapping mutable @@ -1800,11 +1796,9 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_group_by)] - /// /// let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2]; /// - /// let mut iter = slice.group_by_mut(|a, b| a == b); + /// let mut iter = slice.chunk_by_mut(|a, b| a == b); /// /// assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); /// assert_eq!(iter.next(), Some(&mut [3, 3][..])); @@ -1815,24 +1809,22 @@ impl [T] { /// This method can be used to extract the sorted subslices: /// /// ``` - /// #![feature(slice_group_by)] - /// /// let slice = &mut [1, 1, 2, 3, 2, 3, 2, 3, 4]; /// - /// let mut iter = slice.group_by_mut(|a, b| a <= b); + /// let mut iter = slice.chunk_by_mut(|a, b| a <= b); /// /// assert_eq!(iter.next(), Some(&mut [1, 1, 2, 3][..])); /// assert_eq!(iter.next(), Some(&mut [2, 3][..])); /// assert_eq!(iter.next(), Some(&mut [2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "80552")] + #[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] #[inline] - pub fn group_by_mut(&mut self, pred: F) -> GroupByMut<'_, T, F> + pub fn chunk_by_mut(&mut self, pred: F) -> ChunkByMut<'_, T, F> where F: FnMut(&T, &T) -> bool, { - GroupByMut::new(self, pred) + ChunkByMut::new(self, pred) } /// Divides one slice into two at an index. diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 89d2b5ef09383..57ad2ad1af9a3 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -101,7 +101,6 @@ #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(int_roundings)] -#![feature(slice_group_by)] #![feature(split_array)] #![feature(strict_provenance)] #![feature(strict_provenance_atomic_ptr)] From c5c2fb1761e0962c66793f6753cbe8f0cc2d4c26 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Fri, 17 Nov 2023 12:35:46 +0100 Subject: [PATCH 015/676] Improve slice_group_by doc wording --- library/core/src/slice/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index fe18c31df1a8d..2d93ef6fbeb34 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1748,9 +1748,9 @@ impl [T] { /// Returns an iterator over the slice producing non-overlapping runs /// of elements using the predicate to separate them. /// - /// The predicate is called on two elements following themselves, - /// it means the predicate is called on `slice[0]` and `slice[1]` - /// then on `slice[1]` and `slice[2]` and so on. + /// The predicate is called for every pair of consecutive elements, + /// meaning that it is called on `slice[0]` and `slice[1]`, + /// followed by `slice[1]` and `slice[2]`, and so on. /// /// # Examples /// @@ -1789,9 +1789,9 @@ impl [T] { /// Returns an iterator over the slice producing non-overlapping mutable /// runs of elements using the predicate to separate them. /// - /// The predicate is called on two elements following themselves, - /// it means the predicate is called on `slice[0]` and `slice[1]` - /// then on `slice[1]` and `slice[2]` and so on. + /// The predicate is called for every pair of consecutive elements, + /// meaning that it is called on `slice[0]` and `slice[1]`, + /// followed by `slice[1]` and `slice[2]`, and so on. /// /// # Examples /// From 9911d8d9bf4552f0ce05914e2ad239cd3fdc3634 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 20 Nov 2023 20:01:10 +0000 Subject: [PATCH 016/676] freebsd add *stat calls interception support --- src/tools/miri/src/helpers.rs | 15 ++++ .../miri/src/shims/unix/foreign_items.rs | 11 +++ .../src/shims/unix/freebsd/foreign_items.rs | 28 ++++++ src/tools/miri/src/shims/unix/fs.rs | 89 +++++++++++++------ .../src/shims/unix/macos/foreign_items.rs | 15 +--- .../pass-dep/shims/libc-fs-with-isolation.rs | 1 - 6 files changed, 118 insertions(+), 41 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 21f1d684924a0..3651db982b3a1 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -225,6 +225,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { bug!("No field named {} in type {}", name, base.layout().ty); } + /// Search if Project (which must be a struct or union type) contains the `name` field. + fn projectable_has_field>( + &self, + base: &P, + name: &str, + ) -> bool { + let adt = base.layout().ty.ty_adt_def().unwrap(); + for field in adt.non_enum_variant().fields.iter() { + if field.name.as_str() == name { + return true; + } + } + false + } + /// Write an int of the appropriate size to `dest`. The target type may be signed or unsigned, /// we try to do the right thing anyway. `i128` can fit all integer types except for `u128` so /// this method is fine for almost all integer types. diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 23342c8045e80..35036ce078d37 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -155,6 +155,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "lseek64" => { let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let offset = this.read_scalar(offset)?.to_i64()?; + let whence = this.read_scalar(whence)?.to_i32()?; + let result = this.lseek64(fd, offset.into(), whence)?; + this.write_scalar(result, dest)?; + } + "lseek" => { + let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + let whence = this.read_scalar(whence)?.to_i32()?; let result = this.lseek64(fd, offset, whence)?; this.write_scalar(result, dest)?; } diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 7c843e106eacf..64094ac307d2a 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -3,6 +3,7 @@ use rustc_target::spec::abi::Abi; use crate::*; use shims::foreign_items::EmulateForeignItemResult; +use shims::unix::fs::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; pub fn is_dyn_sym(_name: &str) -> bool { @@ -63,6 +64,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(Scalar::from_target_usize(len, this), dest)?; } + // File related shims + // For those, we both intercept `func` and `call@FBSD_1.0` symbols cases + // since freebsd 12 the former form can be expected. + "stat" | "stat@FBSD_1.0" => { + let [path, buf] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_stat(path, buf)?; + this.write_scalar(result, dest)?; + } + "lstat" | "lstat@FBSD_1.0" => { + let [path, buf] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_lstat(path, buf)?; + this.write_scalar(result, dest)?; + } + "fstat" | "fstat@FBSD_1.0" => { + let [fd, buf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_fstat(fd, buf)?; + this.write_scalar(result, dest)?; + } + "readdir_r" | "readdir_r@FBSD_1.0" => { + let [dirp, entry, result] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; + this.write_scalar(result, dest)?; + } + // errno "__error" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index ba40a1b3c321c..b2170c8c87fd3 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -827,24 +827,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn lseek64( &mut self, - fd_op: &OpTy<'tcx, Provenance>, - offset_op: &OpTy<'tcx, Provenance>, - whence_op: &OpTy<'tcx, Provenance>, + fd: i32, + offset: i128, + whence: i32, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescriptor` trait. - let fd = this.read_scalar(fd_op)?.to_i32()?; - let offset = this.read_scalar(offset_op)?.to_i64()?; - let whence = this.read_scalar(whence_op)?.to_i32()?; - let seek_from = if whence == this.eval_libc_i32("SEEK_SET") { SeekFrom::Start(u64::try_from(offset).unwrap()) } else if whence == this.eval_libc_i32("SEEK_CUR") { - SeekFrom::Current(offset) + SeekFrom::Current(i64::try_from(offset).unwrap()) } else if whence == this.eval_libc_i32("SEEK_END") { - SeekFrom::End(offset) + SeekFrom::End(i64::try_from(offset).unwrap()) } else { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; @@ -911,13 +907,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.try_unwrap_io_result(result) } - fn macos_stat( + fn macos_fbsd_stat( &mut self, path_op: &OpTy<'tcx, Provenance>, buf_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - this.assert_target_os("macos", "stat"); + + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { + panic!("`macos_fbsd_stat` should not be called on {}", this.tcx.sess.target.os); + } let path_scalar = this.read_pointer(path_op)?; let path = this.read_path_from_c_str(path_scalar)?.into_owned(); @@ -940,13 +939,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // `lstat` is used to get symlink metadata. - fn macos_lstat( + fn macos_fbsd_lstat( &mut self, path_op: &OpTy<'tcx, Provenance>, buf_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - this.assert_target_os("macos", "lstat"); + + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { + panic!("`macos_fbsd_lstat` should not be called on {}", this.tcx.sess.target.os); + } let path_scalar = this.read_pointer(path_op)?; let path = this.read_path_from_c_str(path_scalar)?.into_owned(); @@ -967,14 +969,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?)) } - fn macos_fstat( + fn macos_fbsd_fstat( &mut self, fd_op: &OpTy<'tcx, Provenance>, buf_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - this.assert_target_os("macos", "fstat"); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { + panic!("`macos_fbsd_fstat` should not be called on {}", this.tcx.sess.target.os); + } let fd = this.read_scalar(fd_op)?.to_i32()?; @@ -1213,7 +1217,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); #[cfg_attr(not(unix), allow(unused_variables))] - let mode = if this.tcx.sess.target.os == "macos" { + let mode = if matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { u32::from(this.read_scalar(mode_op)?.to_u16()?) } else { this.read_scalar(mode_op)?.to_u32()? @@ -1385,7 +1389,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(Scalar::from_maybe_pointer(entry, this)) } - fn macos_readdir_r( + fn macos_fbsd_readdir_r( &mut self, dirp_op: &OpTy<'tcx, Provenance>, entry_op: &OpTy<'tcx, Provenance>, @@ -1393,7 +1397,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - this.assert_target_os("macos", "readdir_r"); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { + panic!("`macos_fbsd_readdir_r` should not be called on {}", this.tcx.sess.target.os); + } let dirp = this.read_target_usize(dirp_op)?; @@ -1424,7 +1430,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // } let entry_place = this.deref_pointer_as(entry_op, this.libc_ty_layout("dirent"))?; - let name_place = this.project_field(&entry_place, 5)?; + let name_place = this.project_field_named(&entry_place, "d_name")?; let file_name = dir_entry.file_name(); // not a Path as there are no separators! let (name_fits, file_name_buf_len) = this.write_os_str_to_c_str( @@ -1448,16 +1454,41 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let file_type = this.file_type_to_d_type(dir_entry.file_type())?; - this.write_int_fields_named( - &[ - ("d_ino", ino.into()), - ("d_seekoff", 0), - ("d_reclen", 0), - ("d_namlen", file_name_len.into()), - ("d_type", file_type.into()), - ], - &entry_place, - )?; + // macOS offset field is d_seekoff + if this.projectable_has_field(&entry_place, "d_seekoff") { + this.write_int_fields_named( + &[ + ("d_ino", ino.into()), + ("d_seekoff", 0), + ("d_reclen", 0), + ("d_namlen", file_name_len.into()), + ("d_type", file_type.into()), + ], + &entry_place, + )?; + // freebsd 12 and onwards had added the d_off field + } else if this.projectable_has_field(&entry_place, "d_off") { + this.write_int_fields_named( + &[ + ("d_fileno", ino.into()), + ("d_off", 0), + ("d_reclen", 0), + ("d_type", file_type.into()), + ("d_namlen", file_name_len.into()), + ], + &entry_place, + )?; + } else { + this.write_int_fields_named( + &[ + ("d_fileno", ino.into()), + ("d_reclen", 0), + ("d_type", file_type.into()), + ("d_namlen", file_name_len.into()), + ], + &entry_place, + )?; + } let result_place = this.deref_pointer(result_op)?; this.write_scalar(this.read_scalar(entry_op)?, &result_place)?; diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 07e19cadd6e32..ecc07e28a2988 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -40,18 +40,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "stat" | "stat64" | "stat$INODE64" => { let [path, buf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.macos_stat(path, buf)?; + let result = this.macos_fbsd_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" | "lstat$INODE64" => { let [path, buf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.macos_lstat(path, buf)?; + let result = this.macos_fbsd_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" | "fstat$INODE64" => { let [fd, buf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.macos_fstat(fd, buf)?; + let result = this.macos_fbsd_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "opendir$INODE64" => { @@ -62,14 +62,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "readdir_r" | "readdir_r$INODE64" => { let [dirp, entry, result] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.macos_readdir_r(dirp, entry, result)?; - this.write_scalar(result, dest)?; - } - "lseek" => { - let [fd, offset, whence] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // macOS is 64bit-only, so this is lseek64 - let result = this.lseek64(fd, offset, whence)?; + let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; this.write_scalar(result, dest)?; } "realpath$DARWIN_EXTSN" => { diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs index adfece586611d..5185db0b0e29f 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs @@ -1,5 +1,4 @@ //@ignore-target-windows: no libc on Windows -//@ignore-target-freebsd: FIXME needs foreign function `stat@FBSD_1.0` //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT" From 4369a787300c22110ae5ea8d520870fd8bc975a0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:16:02 +0100 Subject: [PATCH 017/676] Add triagebot mentions entry for simd intrinsics --- triagebot.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index e4b104cdb8677..8dcfb38e097b5 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -492,6 +492,13 @@ cc = ["@Nadrieril"] message = "Some changes might have occurred in exhaustiveness checking" cc = ["@Nadrieril"] +[mentions."library/core/src/intrinsics/simd.rs"] +message = """ +Some changes occurred to the platform-builtins intrinsics. Make sure all +codegen backends as well as portable-simd get adapted for the changes. +""" +cc = ["@antoyo", "@GuillaumeGomez", "@bjorn3", "@calebzulawski", "@programmerjake"] + [mentions."library/portable-simd"] message = """ Portable SIMD is developed in its own repository. If possible, consider \ From 006ea0356f812f5ee5c7dac944c031ccc6a2dab0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 21 Dec 2023 14:39:14 +0100 Subject: [PATCH 018/676] another trophy --- src/tools/miri/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 3dee742fa0dea..6695f123c7836 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -590,6 +590,7 @@ Definite bugs found: * [Incorrect use of `compare_exchange_weak` in `once_cell`](https://github.com/matklad/once_cell/issues/186) * [Dropping with unaligned pointers in `vec::IntoIter`](https://github.com/rust-lang/rust/pull/106084) * [Deallocating with the wrong layout in new specializations for in-place `Iterator::collect`](https://github.com/rust-lang/rust/pull/118460) +* [Incorrect offset computation for highly-aligned types in `portable-atomic-util`](https://github.com/taiki-e/portable-atomic/pull/138) Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment): From adb6e1b69bfba1e57ba5606797848199733e0f96 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:42:40 +0100 Subject: [PATCH 019/676] Update triagebot.toml --- triagebot.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 8dcfb38e097b5..6acc698ec1b1c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -494,8 +494,8 @@ cc = ["@Nadrieril"] [mentions."library/core/src/intrinsics/simd.rs"] message = """ -Some changes occurred to the platform-builtins intrinsics. Make sure all -codegen backends as well as portable-simd get adapted for the changes. +Some changes occurred to the platform-builtins intrinsics. Make sure the +LLVM backend as well as portable-simd gets adapted for the changes. """ cc = ["@antoyo", "@GuillaumeGomez", "@bjorn3", "@calebzulawski", "@programmerjake"] From a63880c4d3a7e7620f25283999eb4a27516f4816 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 20 Nov 2023 21:55:17 +0100 Subject: [PATCH 020/676] 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 021/676] 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 022/676] 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 0cfbc47b9a32735659f8347872c571bdfeba8424 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 31 Dec 2023 13:29:53 +0000 Subject: [PATCH 023/676] Merge commit '6d355f6844323db03bfd608899613e363e701951' into sync_cg_clif-2023-12-31 --- .github/workflows/main.yml | 16 ++++++---------- .github/workflows/rustc.yml | 5 +++++ rust-toolchain | 2 +- scripts/setup_rust_fork.sh | 15 +++++++-------- src/driver/jit.rs | 2 +- src/global_asm.rs | 2 ++ 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 05dc28d074530..9bbb18fc37fca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -175,14 +175,10 @@ jobs: path: build/cg_clif key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} - - name: Cache cargo bin dir - uses: actions/cache@v3 - with: - path: ~/.cargo/bin - key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-bin-dir-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} - - name: Install hyperfine - run: cargo install hyperfine || true + run: | + sudo apt update + sudo apt install -y hyperfine - name: Prepare dependencies run: ./y.sh prepare @@ -257,14 +253,14 @@ jobs: - name: Upload prebuilt cg_clif if: matrix.os == 'windows-latest' || matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: cg_clif-${{ matrix.env.TARGET_TRIPLE }} path: cg_clif.tar.xz - name: Upload prebuilt cg_clif (cross compile) if: matrix.os != 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: cg_clif-${{ runner.os }}-cross-x86_64-mingw path: cg_clif.tar.xz @@ -283,7 +279,7 @@ jobs: - uses: actions/checkout@v3 - name: Download all built artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: artifacts/ diff --git a/.github/workflows/rustc.yml b/.github/workflows/rustc.yml index cb5dd51fee310..8085dc58263cc 100644 --- a/.github/workflows/rustc.yml +++ b/.github/workflows/rustc.yml @@ -43,6 +43,11 @@ jobs: path: build/cg_clif key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + - name: Install ripgrep + run: | + sudo apt update + sudo apt install -y ripgrep + - name: Prepare dependencies run: ./y.sh prepare diff --git a/rust-toolchain b/rust-toolchain index e1e1760c5977f..a086c0293601f 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-12-24" +channel = "nightly-2023-12-31" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 731828caae2c4..684a5d0729355 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we +# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as # the LLVM backend isn't compiled in here. export CG_CLIF_FORCE_GNU_AS=1 @@ -11,20 +11,19 @@ export CG_CLIF_FORCE_GNU_AS=1 CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build echo "[SETUP] Rust fork" -git clone https://github.com/rust-lang/rust.git --filter=tree:0 || true +git clone --quiet https://github.com/rust-lang/rust.git --filter=tree:0 || true pushd rust git fetch -git checkout -- . -git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')" +git checkout --no-progress -- . +git checkout --no-progress "$(rustc -V | cut -d' ' -f3 | tr -d '(')" + +git submodule update --quiet --init src/tools/cargo library/backtrace library/stdarch git -c user.name=Dummy -c user.email=dummy@example.com -c commit.gpgSign=false \ am ../patches/*-stdlib-*.patch cat > config.toml < {} Linkage::Static => { let name = crate_info.crate_name[&cnum]; - let mut err = sess.struct_err(format!("Can't load static lib {}", name)); + let mut err = sess.dcx().struct_err(format!("Can't load static lib {}", name)); err.note("rustc_codegen_cranelift can only load dylibs in JIT mode."); err.emit(); } diff --git a/src/global_asm.rs b/src/global_asm.rs index af99239d81593..da07b66c762ee 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -154,6 +154,8 @@ pub(crate) fn compile_global_asm( } } else { let mut child = Command::new(std::env::current_exe().unwrap()) + // Avoid a warning about the jobserver fd not being passed + .env_remove("CARGO_MAKEFLAGS") .arg("--target") .arg(&config.target) .arg("--crate-type") From 7ac4515dde285decf97985107f154bf9e08b4a7e Mon Sep 17 00:00:00 2001 From: Brian Romanowski Date: Sun, 31 Dec 2023 15:09:32 -0600 Subject: [PATCH 024/676] 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 543d56938e23865eb70b49f153c71a2057668c79 Mon Sep 17 00:00:00 2001 From: Aneesh Kadiyala <143342960+ARandomDev99@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:30:20 +0530 Subject: [PATCH 025/676] Make `HirEqInterExpr::eq_block` take comments into account This commit: - now makes `HirEqInterExpr::eq_block` take comments into account. Identical code with varying comments will no longer be considered equal. - makes necessary adjustments to UI tests. --- clippy_utils/src/hir_utils.rs | 6 +- .../ui/branches_sharing_code/shared_at_top.rs | 8 +-- .../shared_at_top.stderr | 6 +- .../branches_sharing_code/valid_if_blocks.rs | 12 ++-- .../valid_if_blocks.stderr | 18 ++--- tests/ui/if_same_then_else.rs | 28 +++----- tests/ui/if_same_then_else.stderr | 69 +++++++------------ tests/ui/if_same_then_else2.rs | 18 ++--- tests/ui/if_same_then_else2.stderr | 37 ++++------ tests/ui/match_same_arms2.rs | 4 +- tests/ui/match_same_arms2.stderr | 5 +- 11 files changed, 73 insertions(+), 138 deletions(-) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index e610ed930505b..ea8d3631b0d27 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -134,7 +134,7 @@ impl HirEqInterExpr<'_, '_, '_> { /// Checks whether two blocks are the same. #[expect(clippy::similar_names)] fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool { - use TokenKind::{BlockComment, LineComment, Semi, Whitespace}; + use TokenKind::{Semi, Whitespace}; if left.stmts.len() != right.stmts.len() { return false; } @@ -177,7 +177,7 @@ impl HirEqInterExpr<'_, '_, '_> { return false; } if !eq_span_tokens(self.inner.cx, lstart..lstmt_span.lo, rstart..rstmt_span.lo, |t| { - !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi) + !matches!(t, Whitespace | Semi) }) { return false; } @@ -212,7 +212,7 @@ impl HirEqInterExpr<'_, '_, '_> { return false; } eq_span_tokens(self.inner.cx, lstart..lend, rstart..rend, |t| { - !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi) + !matches!(t, Whitespace | Semi) }) } diff --git a/tests/ui/branches_sharing_code/shared_at_top.rs b/tests/ui/branches_sharing_code/shared_at_top.rs index 44f8b2eabce3b..9af81f6f7cdda 100644 --- a/tests/ui/branches_sharing_code/shared_at_top.rs +++ b/tests/ui/branches_sharing_code/shared_at_top.rs @@ -9,17 +9,16 @@ fn simple_examples() { // Simple if true { - //~^ ERROR: all if blocks contain the same code at the start println!("Hello World!"); println!("I'm branch nr: 1"); } else { println!("Hello World!"); println!("I'm branch nr: 2"); } + //~^^^^^^^ ERROR: all if blocks contain the same code at the start // Else if if x == 0 { - //~^ ERROR: all if blocks contain the same code at the start let y = 9; println!("The value y was set to: `{}`", y); let _z = y; @@ -38,6 +37,7 @@ fn simple_examples() { println!("Ha, Pascal allows you to start the array where you want") } + //~^^^^^^^^^^^^^^^^^^^ ERROR: all if blocks contain the same code at the start // Return a value let _ = if x == 7 { @@ -60,7 +60,6 @@ fn simple_but_suggestion_is_invalid() { // Can't be automatically moved because used_value_name is getting used again let used_value_name = 19; if x == 10 { - //~^ ERROR: all if blocks contain the same code at the start let used_value_name = "Different type"; println!("Str: {}", used_value_name); let _ = 1; @@ -69,6 +68,7 @@ fn simple_but_suggestion_is_invalid() { println!("Str: {}", used_value_name); let _ = 2; } + //~^^^^^^^^^ ERROR: all if blocks contain the same code at the start let _ = used_value_name; // This can be automatically moved as `can_be_overridden` is not used again @@ -101,11 +101,11 @@ fn check_if_same_than_else_mask() { } if x == 2019 { - //~^ ERROR: this `if` has identical blocks println!("This should trigger `IS_SAME_THAN_ELSE` as usual"); } else { println!("This should trigger `IS_SAME_THAN_ELSE` as usual"); } + //~^^^^^ ERROR: this `if` has identical blocks } #[allow(clippy::vec_init_then_push)] diff --git a/tests/ui/branches_sharing_code/shared_at_top.stderr b/tests/ui/branches_sharing_code/shared_at_top.stderr index 9d4d42fb689e4..317d1577226ca 100644 --- a/tests/ui/branches_sharing_code/shared_at_top.stderr +++ b/tests/ui/branches_sharing_code/shared_at_top.stderr @@ -2,7 +2,6 @@ error: all if blocks contain the same code at the start --> $DIR/shared_at_top.rs:11:5 | LL | / if true { -LL | | LL | | println!("Hello World!"); | |_________________________________^ | @@ -21,7 +20,6 @@ error: all if blocks contain the same code at the start --> $DIR/shared_at_top.rs:21:5 | LL | / if x == 0 { -LL | | LL | | let y = 9; LL | | println!("The value y was set to: `{}`", y); LL | | let _z = y; @@ -54,7 +52,6 @@ error: all if blocks contain the same code at the start --> $DIR/shared_at_top.rs:62:5 | LL | / if x == 10 { -LL | | LL | | let used_value_name = "Different type"; LL | | println!("Str: {}", used_value_name); | |_____________________________________________^ @@ -105,13 +102,12 @@ error: this `if` has identical blocks | LL | if x == 2019 { | __________________^ -LL | | LL | | println!("This should trigger `IS_SAME_THAN_ELSE` as usual"); LL | | } else { | |_____^ | note: same as this - --> $DIR/shared_at_top.rs:106:12 + --> $DIR/shared_at_top.rs:105:12 | LL | } else { | ____________^ diff --git a/tests/ui/branches_sharing_code/valid_if_blocks.rs b/tests/ui/branches_sharing_code/valid_if_blocks.rs index 2aeacb89c0cb6..b63819d7c3932 100644 --- a/tests/ui/branches_sharing_code/valid_if_blocks.rs +++ b/tests/ui/branches_sharing_code/valid_if_blocks.rs @@ -107,9 +107,9 @@ fn valid_examples() { // Let's test empty blocks if false { - //~^ ERROR: this `if` has identical blocks } else { } + //~^^^ ERROR: this `if` has identical blocks } /// This makes sure that the `if_same_then_else` masks the `shared_code_in_if_blocks` lint @@ -119,7 +119,6 @@ fn trigger_other_lint() { // Same block if x == 0 { - //~^ ERROR: this `if` has identical blocks let u = 19; println!("How are u today?"); let _ = "This is a string"; @@ -128,6 +127,7 @@ fn trigger_other_lint() { println!("How are u today?"); let _ = "This is a string"; } + //~^^^^^^^^^ ERROR: this `if` has identical blocks // Only same expression let _ = if x == 6 { 7 } else { 7 }; @@ -138,28 +138,24 @@ fn trigger_other_lint() { println!("Well I'm the most important block"); "I'm a pretty string" } else if x == 68 { - //~^ ERROR: this `if` has identical blocks println!("I'm a doppelgänger"); - // Don't listen to my clone below if y == 90 { "=^.^=" } else { ":D" } } else { - // Don't listen to my clone above println!("I'm a doppelgänger"); if y == 90 { "=^.^=" } else { ":D" } }; + //~^^^^^^^^^ ERROR: this `if` has identical blocks if x == 0 { println!("I'm single"); } else if x == 68 { - //~^ ERROR: this `if` has identical blocks println!("I'm a doppelgänger"); - // Don't listen to my clone below } else { - // Don't listen to my clone above println!("I'm a doppelgänger"); } + //~^^^^^ ERROR: this `if` has identical blocks } fn main() {} diff --git a/tests/ui/branches_sharing_code/valid_if_blocks.stderr b/tests/ui/branches_sharing_code/valid_if_blocks.stderr index fcbf12235aa16..0daf2ff6967cd 100644 --- a/tests/ui/branches_sharing_code/valid_if_blocks.stderr +++ b/tests/ui/branches_sharing_code/valid_if_blocks.stderr @@ -3,12 +3,11 @@ error: this `if` has identical blocks | LL | if false { | ______________^ -LL | | LL | | } else { | |_____^ | note: same as this - --> $DIR/valid_if_blocks.rs:111:12 + --> $DIR/valid_if_blocks.rs:110:12 | LL | } else { | ____________^ @@ -25,7 +24,6 @@ error: this `if` has identical blocks | LL | if x == 0 { | _______________^ -LL | | LL | | let u = 19; LL | | println!("How are u today?"); LL | | let _ = "This is a string"; @@ -33,7 +31,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/valid_if_blocks.rs:126:12 + --> $DIR/valid_if_blocks.rs:125:12 | LL | } else { | ____________^ @@ -60,20 +58,17 @@ error: this `if` has identical blocks | LL | } else if x == 68 { | _______________________^ -LL | | LL | | println!("I'm a doppelgänger"); -LL | | // Don't listen to my clone below LL | | LL | | if y == 90 { "=^.^=" } else { ":D" } LL | | } else { | |_____^ | note: same as this - --> $DIR/valid_if_blocks.rs:146:12 + --> $DIR/valid_if_blocks.rs:144:12 | LL | } else { | ____________^ -LL | | // Don't listen to my clone above LL | | println!("I'm a doppelgänger"); LL | | LL | | if y == 90 { "=^.^=" } else { ":D" } @@ -81,22 +76,19 @@ LL | | }; | |_____^ error: this `if` has identical blocks - --> $DIR/valid_if_blocks.rs:155:23 + --> $DIR/valid_if_blocks.rs:153:23 | LL | } else if x == 68 { | _______________________^ -LL | | LL | | println!("I'm a doppelgänger"); -LL | | // Don't listen to my clone below LL | | } else { | |_____^ | note: same as this - --> $DIR/valid_if_blocks.rs:159:12 + --> $DIR/valid_if_blocks.rs:155:12 | LL | } else { | ____________^ -LL | | // Don't listen to my clone above LL | | println!("I'm a doppelgänger"); LL | | } | |_____^ diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index e84b20e9fef07..d53e1383d845c 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -21,7 +21,6 @@ fn foo() -> bool { fn if_same_then_else() { if true { - //~^ ERROR: this `if` has identical blocks Foo { bar: 42 }; 0..10; ..; @@ -38,6 +37,7 @@ fn if_same_then_else() { 0..=10; foo(); } + //~^^^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks if true { Foo { bar: 42 }; @@ -64,19 +64,11 @@ fn if_same_then_else() { foo(); } - let _ = if true { - //~^ ERROR: this `if` has identical blocks - 0.0 - } else { - 0.0 - }; + let _ = if true { 0.0 } else { 0.0 }; + //~^ ERROR: this `if` has identical blocks - let _ = if true { - //~^ ERROR: this `if` has identical blocks - -0.0 - } else { - -0.0 - }; + let _ = if true { -0.0 } else { -0.0 }; + //~^ ERROR: this `if` has identical blocks let _ = if true { 0.0 } else { -0.0 }; @@ -87,15 +79,10 @@ fn if_same_then_else() { foo(); } - let _ = if true { - //~^ ERROR: this `if` has identical blocks - 42 - } else { - 42 - }; + let _ = if true { 42 } else { 42 }; + //~^ ERROR: this `if` has identical blocks if true { - //~^ ERROR: this `if` has identical blocks let bar = if true { 42 } else { 43 }; while foo() { @@ -110,6 +97,7 @@ fn if_same_then_else() { } bar + 1; } + //~^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks if true { let _ = match 42 { diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr index fb33e94e6c3de..281f30f88b46d 100644 --- a/tests/ui/if_same_then_else.stderr +++ b/tests/ui/if_same_then_else.stderr @@ -3,16 +3,16 @@ error: this `if` has identical blocks | LL | if true { | _____________^ -LL | | LL | | Foo { bar: 42 }; LL | | 0..10; +LL | | ..; ... | LL | | foo(); LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:32:12 + --> $DIR/if_same_then_else.rs:31:12 | LL | } else { | ____________^ @@ -29,75 +29,54 @@ LL | | } error: this `if` has identical blocks --> $DIR/if_same_then_else.rs:67:21 | -LL | let _ = if true { - | _____________________^ -LL | | -LL | | 0.0 -LL | | } else { - | |_____^ +LL | let _ = if true { 0.0 } else { 0.0 }; + | ^^^^^^^ | note: same as this - --> $DIR/if_same_then_else.rs:70:12 + --> $DIR/if_same_then_else.rs:67:34 | -LL | } else { - | ____________^ -LL | | 0.0 -LL | | }; - | |_____^ +LL | let _ = if true { 0.0 } else { 0.0 }; + | ^^^^^^^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:74:21 + --> $DIR/if_same_then_else.rs:70:21 | -LL | let _ = if true { - | _____________________^ -LL | | -LL | | -0.0 -LL | | } else { - | |_____^ +LL | let _ = if true { -0.0 } else { -0.0 }; + | ^^^^^^^^ | note: same as this - --> $DIR/if_same_then_else.rs:77:12 + --> $DIR/if_same_then_else.rs:70:35 | -LL | } else { - | ____________^ -LL | | -0.0 -LL | | }; - | |_____^ +LL | let _ = if true { -0.0 } else { -0.0 }; + | ^^^^^^^^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:90:21 + --> $DIR/if_same_then_else.rs:82:21 | -LL | let _ = if true { - | _____________________^ -LL | | -LL | | 42 -LL | | } else { - | |_____^ +LL | let _ = if true { 42 } else { 42 }; + | ^^^^^^ | note: same as this - --> $DIR/if_same_then_else.rs:93:12 + --> $DIR/if_same_then_else.rs:82:33 | -LL | } else { - | ____________^ -LL | | 42 -LL | | }; - | |_____^ +LL | let _ = if true { 42 } else { 42 }; + | ^^^^^^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:97:13 + --> $DIR/if_same_then_else.rs:85:13 | LL | if true { | _____________^ -LL | | LL | | let bar = if true { 42 } else { 43 }; LL | | +LL | | while foo() { ... | LL | | bar + 1; LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:105:12 + --> $DIR/if_same_then_else.rs:92:12 | LL | } else { | ____________^ @@ -110,7 +89,7 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:250:14 + --> $DIR/if_same_then_else.rs:238:14 | LL | if x { | ______________^ @@ -119,7 +98,7 @@ LL | | } else { | |_________^ | note: same as this - --> $DIR/if_same_then_else.rs:252:16 + --> $DIR/if_same_then_else.rs:240:16 | LL | } else { | ________________^ diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs index 0b171f21d0cc4..e23c77b082744 100644 --- a/tests/ui/if_same_then_else2.rs +++ b/tests/ui/if_same_then_else2.rs @@ -13,7 +13,6 @@ fn if_same_then_else2() -> Result<&'static str, ()> { if true { - //~^ ERROR: this `if` has identical blocks for _ in &[42] { let foo: &Option<_> = &Some::(42); if foo.is_some() { @@ -32,20 +31,21 @@ fn if_same_then_else2() -> Result<&'static str, ()> { } } } + //~^^^^^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks if true { - //~^ ERROR: this `if` has identical blocks if let Some(a) = Some(42) {} } else { if let Some(a) = Some(42) {} } + //~^^^^^ ERROR: this `if` has identical blocks if true { - //~^ ERROR: this `if` has identical blocks if let (1, .., 3) = (1, 2, 3) {} } else { if let (1, .., 3) = (1, 2, 3) {} } + //~^^^^^ ERROR: this `if` has identical blocks if true { if let (1, .., 3) = (1, 2, 3) {} @@ -90,19 +90,15 @@ fn if_same_then_else2() -> Result<&'static str, ()> { } // Same NaNs - let _ = if true { - //~^ ERROR: this `if` has identical blocks - f32::NAN - } else { - f32::NAN - }; + let _ = if true { f32::NAN } else { f32::NAN }; + //~^ ERROR: this `if` has identical blocks if true { - //~^ ERROR: this `if` has identical blocks Ok("foo")?; } else { Ok("foo")?; } + //~^^^^^ ERROR: this `if` has identical blocks if true { let foo = ""; @@ -122,13 +118,13 @@ fn if_same_then_else2() -> Result<&'static str, ()> { let foo = "bar"; return Ok(&foo[0..]); } else if true { - //~^ ERROR: this `if` has identical blocks let foo = ""; return Ok(&foo[0..]); } else { let foo = ""; return Ok(&foo[0..]); } + //~^^^^^^^ ERROR: this `if` has identical blocks // False positive `if_same_then_else`: `let (x, y)` vs. `let (y, x)`; see issue #3559. if true { diff --git a/tests/ui/if_same_then_else2.stderr b/tests/ui/if_same_then_else2.stderr index fe68ef2711b59..4e7a7c87dc54b 100644 --- a/tests/ui/if_same_then_else2.stderr +++ b/tests/ui/if_same_then_else2.stderr @@ -3,16 +3,16 @@ error: this `if` has identical blocks | LL | if true { | _____________^ -LL | | LL | | for _ in &[42] { LL | | let foo: &Option<_> = &Some::(42); +LL | | if foo.is_some() { ... | LL | | } LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:25:12 + --> $DIR/if_same_then_else2.rs:24:12 | LL | } else { | ____________^ @@ -31,13 +31,12 @@ error: this `if` has identical blocks | LL | if true { | _____________^ -LL | | LL | | if let Some(a) = Some(42) {} LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:39:12 + --> $DIR/if_same_then_else2.rs:38:12 | LL | } else { | ____________^ @@ -50,13 +49,12 @@ error: this `if` has identical blocks | LL | if true { | _____________^ -LL | | LL | | if let (1, .., 3) = (1, 2, 3) {} LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:46:12 + --> $DIR/if_same_then_else2.rs:45:12 | LL | } else { | ____________^ @@ -67,34 +65,26 @@ LL | | } error: this `if` has identical blocks --> $DIR/if_same_then_else2.rs:93:21 | -LL | let _ = if true { - | _____________________^ -LL | | -LL | | f32::NAN -LL | | } else { - | |_____^ +LL | let _ = if true { f32::NAN } else { f32::NAN }; + | ^^^^^^^^^^^^ | note: same as this - --> $DIR/if_same_then_else2.rs:96:12 + --> $DIR/if_same_then_else2.rs:93:39 | -LL | } else { - | ____________^ -LL | | f32::NAN -LL | | }; - | |_____^ +LL | let _ = if true { f32::NAN } else { f32::NAN }; + | ^^^^^^^^^^^^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:100:13 + --> $DIR/if_same_then_else2.rs:96:13 | LL | if true { | _____________^ -LL | | LL | | Ok("foo")?; LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:103:12 + --> $DIR/if_same_then_else2.rs:98:12 | LL | } else { | ____________^ @@ -103,18 +93,17 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:124:20 + --> $DIR/if_same_then_else2.rs:120:20 | LL | } else if true { | ____________________^ -LL | | LL | | let foo = ""; LL | | return Ok(&foo[0..]); LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:128:12 + --> $DIR/if_same_then_else2.rs:123:12 | LL | } else { | ____________^ diff --git a/tests/ui/match_same_arms2.rs b/tests/ui/match_same_arms2.rs index 525a355f40355..3428ff4590602 100644 --- a/tests/ui/match_same_arms2.rs +++ b/tests/ui/match_same_arms2.rs @@ -13,7 +13,6 @@ fn foo() -> bool { fn match_same_arms() { let _ = match 42 { 42 => { - //~^ ERROR: this match arm has an identical body to the `_` wildcard arm foo(); let mut a = 42 + [23].len() as i32; if true { @@ -32,6 +31,7 @@ fn match_same_arms() { a }, }; + //~^^^^^^^^^^^^^^^^^^^ ERROR: this match arm has an identical body to the `_` wildcard arm let _ = match 42 { 42 => foo(), @@ -146,13 +146,13 @@ fn match_same_arms() { empty!(0); }, 1 => { - //~^ ERROR: this match arm has an identical body to another arm empty!(0); }, x => { empty!(x); }, } + //~^^^^^^^ ERROR: this match arm has an identical body to another arm match_expr_like_matches_macro_priority(); } diff --git a/tests/ui/match_same_arms2.stderr b/tests/ui/match_same_arms2.stderr index 40b20c7e16d28..512ca7413a795 100644 --- a/tests/ui/match_same_arms2.stderr +++ b/tests/ui/match_same_arms2.stderr @@ -2,9 +2,9 @@ error: this match arm has an identical body to the `_` wildcard arm --> $DIR/match_same_arms2.rs:15:9 | LL | / 42 => { -LL | | LL | | foo(); LL | | let mut a = 42 + [23].len() as i32; +LL | | if true { ... | LL | | a LL | | }, @@ -12,7 +12,7 @@ LL | | }, | = help: or try changing either arm body note: `_` wildcard arm here - --> $DIR/match_same_arms2.rs:25:9 + --> $DIR/match_same_arms2.rs:24:9 | LL | / _ => { LL | | foo(); @@ -122,7 +122,6 @@ LL | 1 => { | ^ help: try merging the arm patterns: `1 | 0` | _________| | | -LL | | LL | | empty!(0); LL | | }, | |_________^ From c427754b52415a1fb11c83aa278b5fec21146b27 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 2 Jan 2024 20:39:31 +0000 Subject: [PATCH 026/676] Add platform support matrix Fixes rust-lang/rustc_codegen_cranelift#1441 --- Readme.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Readme.md b/Readme.md index ca6ecdf1d0e88..1c48097da2aae 100644 --- a/Readme.md +++ b/Readme.md @@ -62,6 +62,27 @@ $ ./test.sh For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.sh`. +## Platform support + +|OS \ architecture|x86\_64|AArch64|Riscv64|s390x (System-Z)| +|---|---|---|---|---| +|Linux|✅|✅|✅[^no-rustup]|✅[^no-rustup]| +|FreeBSD|✅[^no-rustup]|❓|❓|❓| +|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]| +|Other unixes|❓|❓|❓|❓| +|macOS|✅|❌[^apple-silicon]|N/A|N/A| +|Windows|✅[^no-rustup]|❌|N/A|N/A| + +✅: Fully supported and tested +❓: Maybe supported, not tested +❌: Not supported at all + +Not all targets are available as rustup component for nightly. See notes in the platform support matrix. + +[^xcoff]: XCOFF object file format is not supported. +[^apple-silicon]: Tracked in [#1248](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1248). +[^no-rustup]: Not available as rustup component for nightly. You can build it yourself. + ## Usage rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects. From 45d8c121ba02c825379b655d8dd74e1843e98d62 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:17:00 +0000 Subject: [PATCH 027/676] Return architecturally mandated target features to rustc In the future the actual target features that Cranelift enables should be returned here, but for now this works. Fixes rust-lang/rustc_codegen_cranelift#1438 --- src/lib.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b482f0dd2f0ab..f327577eb4d32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,7 @@ use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::config::OutputFilenames; use rustc_session::Session; -use rustc_span::Symbol; +use rustc_span::{sym, Symbol}; pub use crate::config::*; use crate::prelude::*; @@ -190,8 +190,17 @@ impl CodegenBackend for CraneliftCodegenBackend { } } - fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec { - vec![] // FIXME necessary for #[cfg(target_feature] + fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec { + // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] + if sess.target.arch == "x86_64" && sess.target.os != "none" { + // x86_64 mandates SSE2 support + vec![Symbol::intern("fxsr"), sym::sse, Symbol::intern("sse2")] + } else if sess.target.arch == "aarch64" && sess.target.os != "none" { + // AArch64 mandates Neon support + vec![sym::neon] + } else { + vec![] + } } fn print_version(&self) { From 3b8794edf4b930c3de435cdc436f00e7b9e72cf8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:08:32 +0000 Subject: [PATCH 028/676] Fix xmm operands in inline assembly --- src/inline_asm.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 6b9cec39d7020..1d0d7ee75de2f 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -506,10 +506,34 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { if self.options.contains(InlineAsmOptions::ATT_SYNTAX) { generated_asm.push('%'); } - self.registers[*operand_idx] - .unwrap() - .emit(&mut generated_asm, self.arch, *modifier) - .unwrap(); + + let reg = self.registers[*operand_idx].unwrap(); + match self.arch { + InlineAsmArch::X86_64 => match reg { + InlineAsmReg::X86(reg) + if reg as u32 >= X86InlineAsmReg::xmm0 as u32 + && reg as u32 <= X86InlineAsmReg::xmm15 as u32 => + { + // rustc emits x0 rather than xmm0 + let class = match *modifier { + None | Some('x') => "xmm", + Some('y') => "ymm", + Some('z') => "zmm", + _ => unreachable!(), + }; + write!( + generated_asm, + "{class}{}", + reg as u32 - X86InlineAsmReg::xmm0 as u32 + ) + .unwrap(); + } + _ => reg + .emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier) + .unwrap(), + }, + _ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(), + } } CInlineAsmOperand::Const { ref value } => { generated_asm.push_str(value); From c8f5d35508e062bd2d95e6c03429bfec831db6d3 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 2 Jan 2024 22:18:00 +0100 Subject: [PATCH 029/676] Restructure x86 signed pack instructions This reduces the amount of duplicated code and the chance for bugs. I validated the new code for correctness against LLVM using the following script. It found many bugs in the implementation until I was finally able to get it correct and passing. ```rust //! Test for x86 pack instructions. Prints deterministic results, use it to compare backends. use std::arch::x86_64::{self, __m128i, __m256i}; use rand::{rngs::SmallRng, Rng, SeedableRng}; fn main() { let rng = &mut SmallRng::seed_from_u64(123); for _ in 0..100_000 { unsafe { sse_test(rng); avx_test(rng); } } } unsafe fn sse_test(rng: &mut SmallRng) { print_sse_8(x86_64::_mm_packus_epi16(sse16(rng), sse16(rng))); print_sse_8(x86_64::_mm_packs_epi16(sse16(rng), sse16(rng))); print_sse_16(x86_64::_mm_packus_epi32(sse32(rng), sse32(rng))); print_sse_16(x86_64::_mm_packs_epi32(sse32(rng), sse32(rng))); } unsafe fn avx_test(rng: &mut SmallRng) { print_avx_8(x86_64::_mm256_packs_epi16(avx16(rng), avx16(rng))); print_avx_8(x86_64::_mm256_packs_epi16(avx16(rng), avx16(rng))); print_avx_16(x86_64::_mm256_packus_epi32(avx32(rng), avx32(rng))); print_avx_16(x86_64::_mm256_packs_epi32(avx32(rng), avx32(rng))); } fn print_sse_8(t: __m128i) { let ints = unsafe { std::mem::transmute::<_, [i8; 16]>(t) }; println!("{ints:?}"); } fn print_sse_16(t: __m128i) { let ints = unsafe { std::mem::transmute::<_, [i16; 8]>(t) }; println!("{ints:?}"); } fn print_avx_8(t: __m256i) { let ints = unsafe { std::mem::transmute::<_, [i8; 32]>(t) }; println!("{ints:?}"); } fn print_avx_16(t: __m256i) { let ints = unsafe { std::mem::transmute::<_, [i16; 16]>(t) }; println!("{ints:?}"); } fn sse16(rand: &mut SmallRng) -> __m128i { unsafe { std::mem::transmute([(); 8].map(|()| i16(rand))) } } fn sse32(rand: &mut SmallRng) -> __m128i { unsafe { std::mem::transmute([(); 4].map(|()| i32(rand))) } } fn avx16(rand: &mut SmallRng) -> __m256i { unsafe { std::mem::transmute([(); 16].map(|()| i16(rand))) } } fn avx32(rand: &mut SmallRng) -> __m256i { unsafe { std::mem::transmute([(); 8].map(|()| i32(rand))) } } fn i16(rand: &mut SmallRng) -> i16 { if rand.gen() { rand.gen::() } else { rand.gen::() as i16 } } fn i32(rand: &mut SmallRng) -> i32 { if rand.gen() { rand.gen::() } else { rand.gen::() as i32 } } ``` --- src/intrinsics/llvm_x86.rs | 328 +++++++++++++++---------------------- 1 file changed, 132 insertions(+), 196 deletions(-) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 81114cbf40d83..445622fc539bc 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -610,230 +610,56 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi16&ig_expand=4903 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i16); - assert_eq!(ret_lane_ty, fx.tcx.types.u8); - assert_eq!(lane_count * 2, ret_lane_count); - - let zero = fx.bcx.ins().iconst(types::I16, 0); - let max_u8 = fx.bcx.ins().iconst(types::I16, 255); - let ret_lane_layout = fx.layout_of(fx.tcx.types.u8); - - for idx in 0..lane_count { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::U8, PackWidth::Sse); + } - for idx in 0..lane_count { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); + "llvm.x86.sse2.packsswb.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi16&ig_expand=4848 + intrinsic_args!(fx, args => (a, b); intrinsic); - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::S8, PackWidth::Sse); } "llvm.x86.avx2.packuswb" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi16&ig_expand=4906 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i16); - assert_eq!(ret_lane_ty, fx.tcx.types.u8); - assert_eq!(lane_count * 2, ret_lane_count); - - let zero = fx.bcx.ins().iconst(types::I16, 0); - let max_u8 = fx.bcx.ins().iconst(types::I16, 255); - let ret_lane_layout = fx.layout_of(fx.tcx.types.u8); - - for idx in 0..lane_count / 2 { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::U8, PackWidth::Avx); } - "llvm.x86.sse2.packssdw.128" => { - // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32&ig_expand=4889 + "llvm.x86.avx2.packsswb" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi16&ig_expand=4851 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i32); - assert_eq!(ret_lane_ty, fx.tcx.types.i16); - assert_eq!(lane_count * 2, ret_lane_count); - - let min_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MIN) as u32 as i64); - let max_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MAX) as u32 as i64); - let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); - - for idx in 0..lane_count { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::S8, PackWidth::Avx); } "llvm.x86.sse41.packusdw" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi32&ig_expand=4912 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i32); - assert_eq!(ret_lane_ty, fx.tcx.types.u16); - assert_eq!(lane_count * 2, ret_lane_count); - - let min_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MIN)); - let max_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MAX)); - let ret_lane_layout = fx.layout_of(fx.tcx.types.u16); + pack_instruction(fx, a, b, ret, PackSize::U16, PackWidth::Sse); + } - for idx in 0..lane_count { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_u16); - let sat = fx.bcx.ins().smin(sat, max_u16); - let res = fx.bcx.ins().ireduce(types::I16, sat); + "llvm.x86.sse2.packssdw.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32&ig_expand=4889 + intrinsic_args!(fx, args => (a, b); intrinsic); - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::S16, PackWidth::Sse); + } - for idx in 0..lane_count { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_u16); - let sat = fx.bcx.ins().smin(sat, max_u16); - let res = fx.bcx.ins().ireduce(types::I16, sat); + "llvm.x86.avx2.packusdw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi32&ig_expand=4883 + intrinsic_args!(fx, args => (a, b); intrinsic); - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::U16, PackWidth::Avx); } "llvm.x86.avx2.packssdw" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi32&ig_expand=4892 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i32); - assert_eq!(ret_lane_ty, fx.tcx.types.i16); - assert_eq!(lane_count * 2, ret_lane_count); - - let min_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MIN) as u32 as i64); - let max_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MAX) as u32 as i64); - let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); - - for idx in 0..lane_count / 2 { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::S16, PackWidth::Avx); } "llvm.x86.fma.vfmaddsub.ps" @@ -1407,3 +1233,113 @@ fn llvm_add_sub<'tcx>( (cb_out, c) } + +enum PackSize { + U8, + U16, + S8, + S16, +} + +impl PackSize { + fn ret_clif_type(&self) -> Type { + match self { + Self::U8 | Self::S8 => types::I8, + Self::U16 | Self::S16 => types::I16, + } + } + fn src_clif_type(&self) -> Type { + match self { + Self::U8 | Self::S8 => types::I16, + Self::U16 | Self::S16 => types::I32, + } + } + fn src_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match self { + Self::U8 | Self::S8 => tcx.types.i16, + Self::U16 | Self::S16 => tcx.types.i32, + } + } + fn ret_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match self { + Self::U8 => tcx.types.u8, + Self::S8 => tcx.types.i8, + Self::U16 => tcx.types.u16, + Self::S16 => tcx.types.i16, + } + } + fn max(&self) -> i64 { + match self { + Self::U8 => u8::MAX as u64 as i64, + Self::S8 => i8::MAX as u8 as u64 as i64, + Self::U16 => u16::MAX as u64 as i64, + Self::S16 => i16::MAX as u64 as u64 as i64, + } + } + fn min(&self) -> i64 { + match self { + Self::U8 | Self::U16 => 0, + Self::S8 => i16::from(i8::MIN) as u16 as i64, + Self::S16 => i32::from(i16::MIN) as u32 as i64, + } + } +} + +enum PackWidth { + Sse = 1, + Avx = 2, +} +impl PackWidth { + fn divisor(&self) -> u64 { + match self { + Self::Sse => 1, + Self::Avx => 2, + } + } +} + +fn pack_instruction<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + a: CValue<'tcx>, + b: CValue<'tcx>, + ret: CPlace<'tcx>, + ret_size: PackSize, + width: PackWidth, +) { + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (src_lane_count, src_lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(src_lane_ty, ret_size.src_ty(fx.tcx)); + assert_eq!(ret_lane_ty, ret_size.ret_ty(fx.tcx)); + assert_eq!(src_lane_count * 2, ret_lane_count); + + let min = fx.bcx.ins().iconst(ret_size.src_clif_type(), ret_size.min()); + let max = fx.bcx.ins().iconst(ret_size.src_clif_type(), ret_size.max()); + let ret_lane_layout = fx.layout_of(ret_size.ret_ty(fx.tcx)); + + let mut round = |source: CValue<'tcx>, source_offset: u64, dest_offset: u64| { + let step_amount = src_lane_count / width.divisor(); + let dest_offset = step_amount * dest_offset; + for idx in 0..step_amount { + let lane = source.value_lane(fx, step_amount * source_offset + idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min); + let sat = match ret_size { + PackSize::U8 | PackSize::U16 => fx.bcx.ins().umin(sat, max), + PackSize::S8 | PackSize::S16 => fx.bcx.ins().smin(sat, max), + }; + let res = fx.bcx.ins().ireduce(ret_size.ret_clif_type(), sat); + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, dest_offset + idx).write_cvalue(fx, res_lane); + } + }; + + round(a, 0, 0); + round(b, 0, 1); + + if let PackWidth::Avx = width { + round(a, 1, 2); + round(b, 1, 3); + } +} From 22019dbac879ae899c1ab13ad48503af28c3802b Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 3 Jan 2024 20:28:08 +0100 Subject: [PATCH 030/676] Mention correctness test --- src/intrinsics/llvm_x86.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 445622fc539bc..24a5df1630de8 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -1298,6 +1298,8 @@ impl PackWidth { } } +/// Implement an x86 pack instruction with the intrinsic `_mm{,256}pack{us,s}_epi{16,32}`. +/// Validated for correctness against LLVM, see commit `c8f5d35508e062bd2d95e6c03429bfec831db6d3`. fn pack_instruction<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, a: CValue<'tcx>, From 6fea128f8c859a3f63e6ca684083419ca00d58d3 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 3 Jan 2024 21:23:55 +0100 Subject: [PATCH 031/676] Use `rust-analyzer.rustc.source` to get r-a working with rustc --- .vscode/settings.json | 3 ++- Readme.md | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 834a1362caf32..491646ce59bb3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,9 @@ { "editor.formatOnSave": true, - // source for rustc_* is not included in the rust-src component; disable the errors about this + // in case rustc.source is disabled for performance reasons; disable the errors about this "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"], + "rust-analyzer.rustc.source": "discover", "rust-analyzer.imports.granularity.enforce": true, "rust-analyzer.imports.granularity.group": "module", "rust-analyzer.imports.prefix": "crate", diff --git a/Readme.md b/Readme.md index 1c48097da2aae..4f45526196397 100644 --- a/Readme.md +++ b/Readme.md @@ -121,6 +121,8 @@ You need to do this steps to successfully compile and use the cranelift backend * (Optional) run tests: `rustup run stage2 ./y.sh test` 8. Now you can use your cg_clif build to compile other Rust programs, e.g. you can open any Rust crate and run commands like `$RustCheckoutDir/compiler/rustc_codegen_cranelift/dist/cargo-clif build --release`. +You can also set `rust-analyzer.rustc.source` to your rust workspace to get rust-analyzer to understand your changes. + ## Configuration See the documentation on the `BackendConfig` struct in [config.rs](src/config.rs) for all From 16e117cf964064f8f70ab2e55f24ed37e1e9a4ee Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Fri, 5 Jan 2024 02:52:37 +0000 Subject: [PATCH 032/676] 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 74987d04fc3f8b85be2cdbdddc3ea3e1e09a6ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 5 Jan 2024 22:40:25 +0100 Subject: [PATCH 033/676] fix a couple of clippy warnings --- src/driver/aot.rs | 2 +- src/inline_asm.rs | 4 ++-- src/intrinsics/simd.rs | 4 ++-- src/lib.rs | 7 ++----- src/unsize.rs | 7 +++---- src/vtable.rs | 2 +- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index e77b0cd0721b2..6cfbb52e92180 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -467,7 +467,7 @@ pub(crate) fn run_aot( let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); let metadata_cgu_name = cgu_name_builder - .build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")) + .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata")) .as_str() .to_string(); diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 1d0d7ee75de2f..7793b1b70924b 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -52,7 +52,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( } let operands = operands - .into_iter() + .iter() .map(|operand| match *operand { InlineAsmOperand::In { reg, ref value } => CInlineAsmOperand::In { reg, @@ -763,7 +763,7 @@ fn call_inline_asm<'tcx>( }, ) .unwrap(); - let inline_asm_func = fx.module.declare_func_in_func(inline_asm_func, &mut fx.bcx.func); + let inline_asm_func = fx.module.declare_func_in_func(inline_asm_func, fx.bcx.func); if fx.clif_comments.enabled() { fx.add_comment(inline_asm_func, asm_name); } diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 78ea7c2dbfc39..59dfba31a0a4e 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -293,7 +293,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } ret.write_cvalue(fx, base); - let ret_lane = ret.place_lane(fx, idx.try_into().unwrap()); + let ret_lane = ret.place_lane(fx, idx.into()); ret_lane.write_cvalue(fx, val); } @@ -340,7 +340,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ); } - let ret_lane = v.value_lane(fx, idx.try_into().unwrap()); + let ret_lane = v.value_lane(fx, idx.into()); ret.write_cvalue(fx, ret_lane); } diff --git a/src/lib.rs b/src/lib.rs index f327577eb4d32..635ff0ba7097e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -314,16 +314,13 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc { - let builder = cranelift_native::builder_with_options(true).unwrap(); - builder - } + Some("native") => cranelift_native::builder_with_options(true).unwrap(), Some(value) => { let mut builder = cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| { sess.dcx().fatal(format!("can't compile for {}: {}", target_triple, err)); }); - if let Err(_) = builder.enable(value) { + if builder.enable(value).is_err() { sess.dcx() .fatal("the specified target cpu isn't currently supported by Cranelift."); } diff --git a/src/unsize.rs b/src/unsize.rs index f777e11371f13..acfa461a6f30b 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -28,10 +28,9 @@ pub(crate) fn unsized_info<'tcx>( .bcx .ins() .iconst(fx.pointer_type, len.eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64), - ( - &ty::Dynamic(ref data_a, _, src_dyn_kind), - &ty::Dynamic(ref data_b, _, target_dyn_kind), - ) if src_dyn_kind == target_dyn_kind => { + (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind)) + if src_dyn_kind == target_dyn_kind => + { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { diff --git a/src/vtable.rs b/src/vtable.rs index 41ea0b122de73..d2254d4c15e6f 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -95,7 +95,7 @@ pub(crate) fn get_vtable<'tcx>( let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref)); let data_id = data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not); - let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); + let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func); if fx.clif_comments.enabled() { fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id)); } From 853504df238835208d8a565cbb532918d84492c6 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Fri, 5 Jan 2024 22:34:43 +0000 Subject: [PATCH 034/676] Remove feature not required by `Ipv6Addr::to_cononical` doctest The feature does not seem to be required by this doctest. --- library/core/src/net/ip_addr.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 1ef876a3163c9..762d1caad4b38 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1860,7 +1860,6 @@ impl Ipv6Addr { /// # Examples /// /// ``` - /// #![feature(ip)] /// use std::net::Ipv6Addr; /// /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false); From 837c0305c6e61c1591b0c59935bb71df11b3638e Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 22 Dec 2023 15:12:01 +0300 Subject: [PATCH 035/676] Update test for `E0796` and `static_mut_ref` lint --- example/mini_core_hello_world.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index a1cdf31c68a00..2a7b1107ffcaa 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -111,6 +111,9 @@ fn start( } static mut NUM: u8 = 6 * 7; + +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint +#[allow(static_mut_ref)] static NUM_REF: &'static u8 = unsafe { &NUM }; unsafe fn zeroed() -> T { From e6570dccccd85f5bfc8497bbd4db615f1d2fdbd2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 17:03:10 +1100 Subject: [PATCH 036/676] Use chaining for `DiagnosticBuilder` construction and `emit`. To avoid the use of a mutable local variable, and because it reads more nicely. --- src/driver/jit.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index a8d8fb189e2e0..50d9f287e74c9 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -321,9 +321,10 @@ fn dep_symbol_lookup_fn( Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { let name = crate_info.crate_name[&cnum]; - let mut err = sess.dcx().struct_err(format!("Can't load static lib {}", name)); - err.note("rustc_codegen_cranelift can only load dylibs in JIT mode."); - err.emit(); + sess.dcx() + .struct_err(format!("Can't load static lib {}", name)) + .note("rustc_codegen_cranelift can only load dylibs in JIT mode.") + .emit(); } Linkage::Dynamic => { dylib_paths.push(src.dylib.as_ref().unwrap().0.clone()); From 1eaeaaf08b7135fd8d41339b90fdb6d189c89d69 Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 7 Jan 2024 21:16:22 -0800 Subject: [PATCH 037/676] 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 038/676] 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 039/676] 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 2b3cd46832d99218576b5d01c910a64a4330b542 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Wed, 29 Nov 2023 12:49:48 +0700 Subject: [PATCH 040/676] Improved support of collapse_debuginfo attribute for macros. --- src/debuginfo/line_info.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index 6230ca15d6e10..d1b21d0a0b6c5 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -68,15 +68,7 @@ impl DebugContext { // In order to have a good line stepping behavior in debugger, we overwrite debug // locations of macro expansions with that of the outermost expansion site (when the macro is // annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided). - let span = if tcx.should_collapse_debuginfo(span) { - span - } else { - // Walk up the macro expansion chain until we reach a non-expanded span. - // We also stop at the function body level because no line stepping can occur - // at the level above that. - rustc_span::hygiene::walk_chain(span, function_span.ctxt()) - }; - + let span = tcx.collapsed_debuginfo(span, function_span); match tcx.sess.source_map().lookup_line(span.lo()) { Ok(SourceFileAndLine { sf: file, line }) => { let line_pos = file.lines()[line]; From 47443364e812ccdd3fb36f5f87503d075454244e Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 8 Jan 2024 09:46:34 -0500 Subject: [PATCH 041/676] Run the tier 2 sysroots job on a schedule, not push --- src/tools/miri/.github/workflows/sysroots.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/.github/workflows/sysroots.yml b/src/tools/miri/.github/workflows/sysroots.yml index 509521e7478b0..96d7d4d111851 100644 --- a/src/tools/miri/.github/workflows/sysroots.yml +++ b/src/tools/miri/.github/workflows/sysroots.yml @@ -1,8 +1,8 @@ name: Tier 2 sysroots -on: push -# schedule: -# - cron: '44 4 * * *' # At 4:44 UTC every day. +on: + schedule: + - cron: '44 4 * * *' # At 4:44 UTC every day. defaults: run: From 6dd0772707eb50a8129eb0a748cd9ef3de6a754a Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 22 Dec 2023 21:56:58 -0800 Subject: [PATCH 042/676] Emit suggestion when trying to write exclusive ranges as `..<` --- .../rustc_parse/src/parser/diagnostics.rs | 25 ++++++++-- compiler/rustc_parse/src/parser/expr.rs | 10 +++- tests/ui/parser/range-exclusive-dotdotlt.rs | 43 +++++++++++++++++ .../ui/parser/range-exclusive-dotdotlt.stderr | 46 +++++++++++++++++++ 4 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 tests/ui/parser/range-exclusive-dotdotlt.rs create mode 100644 tests/ui/parser/range-exclusive-dotdotlt.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a9cf26d991c71..dc7a4d5aa3831 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -23,7 +23,7 @@ use crate::parser; use crate::parser::attr::InnerAttrPolicy; use rustc_ast as ast; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind}; +use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::AttrTokenTree; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ @@ -448,12 +448,11 @@ impl<'a> Parser<'a> { }) } - let mut expected = edible + self.expected_tokens.extend(edible.iter().chain(inedible).cloned().map(TokenType::Token)); + let mut expected = self + .expected_tokens .iter() - .chain(inedible) .cloned() - .map(TokenType::Token) - .chain(self.expected_tokens.iter().cloned()) .filter(|token| { // Filter out suggestions that suggest the same token which was found and deemed incorrect. fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool { @@ -2927,6 +2926,22 @@ impl<'a> Parser<'a> { Ok(()) } + /// Check for exclusive ranges written as `..<` + pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: PErr<'a>) -> PErr<'a> { + if maybe_lt == token::Lt + && (self.expected_tokens.contains(&TokenType::Token(token::Gt)) + || matches!(self.token.kind, token::Literal(..))) + { + err.span_suggestion( + maybe_lt.span, + "remove the `<` to write an exclusive range", + "", + Applicability::MachineApplicable, + ); + } + err + } + pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool { (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) && self.look_ahead(3, |tok| tok == short_kind) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index db777266b59d2..7f4d26b370f1a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -483,7 +483,11 @@ impl<'a> Parser<'a> { cur_op_span: Span, ) -> PResult<'a, P> { let rhs = if self.is_at_start_of_range_notation_rhs() { - Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?) + let maybe_lt = self.token.clone(); + Some( + self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed) + .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?, + ) } else { None }; @@ -532,11 +536,13 @@ impl<'a> Parser<'a> { let attrs = self.parse_or_use_outer_attributes(attrs)?; self.collect_tokens_for_expr(attrs, |this, attrs| { let lo = this.token.span; + let maybe_lt = this.look_ahead(1, |t| t.clone()); this.bump(); let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed) - .map(|x| (lo.to(x.span), Some(x)))? + .map(|x| (lo.to(x.span), Some(x))) + .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? } else { (lo, None) }; diff --git a/tests/ui/parser/range-exclusive-dotdotlt.rs b/tests/ui/parser/range-exclusive-dotdotlt.rs new file mode 100644 index 0000000000000..5752566026f02 --- /dev/null +++ b/tests/ui/parser/range-exclusive-dotdotlt.rs @@ -0,0 +1,43 @@ +fn foo() { + let _ = 0..<10; + //~^ ERROR: expected type, found `10` + //~| HELP: remove the `<` to write an exclusive range +} + +fn bar() { + let _ = 0..`, or `as`, found `;` + //~| HELP: remove the `<` to write an exclusive range +} + +fn baz() { + let _ = ; + //~^ ERROR: expected `::`, found `;` +} + +fn qux() { + let _ = [1, 2, 3][..<1]; + //~^ ERROR: expected type, found `1` + //~| HELP: remove the `<` to write an exclusive range +} + +fn quux() { + let _ = [1, 2, 3][..`, or `as`, found `]` + //~| HELP: remove the `<` to write an exclusive range +} + +fn foobar() { + let _ = [1, 2, 3][..]; + //~^ ERROR: expected `::`, found `]` +} + +fn ok1() { + let _ = [1, 2, 3][..::default()]; +} + +fn ok2() { + let _ = 0..::default(); +} + +fn main() {} diff --git a/tests/ui/parser/range-exclusive-dotdotlt.stderr b/tests/ui/parser/range-exclusive-dotdotlt.stderr new file mode 100644 index 0000000000000..af25e1df343de --- /dev/null +++ b/tests/ui/parser/range-exclusive-dotdotlt.stderr @@ -0,0 +1,46 @@ +error: expected type, found `10` + --> $DIR/range-exclusive-dotdotlt.rs:2:17 + | +LL | let _ = 0..<10; + | -^^ expected type + | | + | help: remove the `<` to write an exclusive range + +error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;` + --> $DIR/range-exclusive-dotdotlt.rs:8:20 + | +LL | let _ = 0.. $DIR/range-exclusive-dotdotlt.rs:14:18 + | +LL | let _ = ; + | ^ expected `::` + +error: expected type, found `1` + --> $DIR/range-exclusive-dotdotlt.rs:19:26 + | +LL | let _ = [1, 2, 3][..<1]; + | -^ expected type + | | + | help: remove the `<` to write an exclusive range + +error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]` + --> $DIR/range-exclusive-dotdotlt.rs:25:29 + | +LL | let _ = [1, 2, 3][.. $DIR/range-exclusive-dotdotlt.rs:31:30 + | +LL | let _ = [1, 2, 3][..]; + | ^ expected `::` + +error: aborting due to 6 previous errors + From 24aefa0e5d134526c8e29c5603dcb4d42637968a Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Mon, 8 Jan 2024 16:58:58 -0800 Subject: [PATCH 043/676] 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 044/676] 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 045/676] 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 046/676] 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 047/676] 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 048/676] 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 049/676] 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 050/676] 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 c2d071c11c008b08d841d30bae40f8acfdac0c6e Mon Sep 17 00:00:00 2001 From: Eugene Date: Tue, 9 Jan 2024 06:50:17 -0800 Subject: [PATCH 051/676] Documentation edits for arc_with_non_send_sync Arc's documentation uses the term "thread", aligning to that terminology. Fix typo in "Rc". --- clippy_lints/src/arc_with_non_send_sync.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index 657d52d0e9e17..58738d5287883 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -14,8 +14,8 @@ declare_clippy_lint! { /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`. /// /// ### Why is this bad? - /// `Arc` is an Atomic `RC` and guarantees that updates to the reference counter are - /// Atomic. This is useful in multiprocessing scenarios. To send an `Arc` across processes + /// `Arc` is an Atomic `Rc` and guarantees that updates to the reference counter are + /// Atomic. This is useful in multithreading scenarios. To send an `Arc` across threads /// and make use of the atomic ref counter, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E), /// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc` /// From 0dc13d7acb0118d6c14a9209d921e5278e829458 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:16:09 +0100 Subject: [PATCH 052/676] Implement _mm_prefetch as nop --- src/intrinsics/llvm.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index a38a728c926d8..9c686eba5e030 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -35,6 +35,10 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( } match intrinsic { + "llvm.prefetch" => { + // Nothing to do. This is merely a perf hint. + } + _ if intrinsic.starts_with("llvm.ctlz.v") => { intrinsic_args!(fx, args => (a); intrinsic); From 7a75766c41893b39352171dd313557f79f2b9f9d Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Wed, 10 Jan 2024 05:03:16 +0000 Subject: [PATCH 053/676] 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 548e12ffdeafb..bdf2416a20e61 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -5bcd86d89b2b7b6a490f7e075dd4eb346deb5f98 +94807670a6a3834cc9b71b0b803d49d307c9ba5d From 281ceb2bd2b2dd5f6ac201f585a2de2d21a41250 Mon Sep 17 00:00:00 2001 From: ardi Date: Wed, 10 Jan 2024 10:26:18 +0100 Subject: [PATCH 054/676] Document the struct and a few methods --- compiler/rustc_index/src/vec.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 66c5cc774b224..3148b054790fc 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -12,10 +12,26 @@ use std::vec; use crate::{Idx, IndexSlice}; /// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`. +/// Its purpose is to avoid mixing indexes. /// /// While it's possible to use `u32` or `usize` directly for `I`, /// you almost certainly want to use a [`newtype_index!`]-generated type instead. /// +/// This allows to index the IndexVec with the new index type: +/// +/// ``` +/// use crate as rustc_index; +/// use rustc_index::{IndexVec, newtype_index}; +/// +/// newtype_index! { +/// pub struct MyIdx {} +/// } +/// +/// let my_index_vec: IndexVec = IndexVec::from_raw(vec![0,1,2,3]); +/// let idx: MyIdx = MyIdx::from_u32(2); +/// assert_eq!(my_index_vec[idx], 2); +/// ``` +/// /// [`newtype_index!`]: ../macro.newtype_index.html #[derive(Clone, PartialEq, Eq, Hash)] #[repr(transparent)] @@ -25,11 +41,13 @@ pub struct IndexVec { } impl IndexVec { + /// Constructs a new, empty `IndexVec`. #[inline] pub const fn new() -> Self { IndexVec::from_raw(Vec::new()) } + /// Constructs a new `IndexVec` from a `Vec` #[inline] pub const fn from_raw(raw: Vec) -> Self { IndexVec { raw, _marker: PhantomData } @@ -59,6 +77,7 @@ impl IndexVec { IndexVec::from_raw(vec![elem; universe.len()]) } + /// Creates a new `IndexVec` with n copies of `elem` #[inline] pub fn from_elem_n(elem: T, n: usize) -> Self where From 1bf3aee3811b92d5833154fd35b98159a233b938 Mon Sep 17 00:00:00 2001 From: ardi Date: Wed, 10 Jan 2024 11:17:46 +0100 Subject: [PATCH 055/676] Oh well --- compiler/rustc_index/src/vec.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 3148b054790fc..3c66e6dde1c2e 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -17,27 +17,15 @@ use crate::{Idx, IndexSlice}; /// While it's possible to use `u32` or `usize` directly for `I`, /// you almost certainly want to use a [`newtype_index!`]-generated type instead. /// -/// This allows to index the IndexVec with the new index type: +/// This allows to index the IndexVec with the new index type /// -/// ``` -/// use crate as rustc_index; -/// use rustc_index::{IndexVec, newtype_index}; -/// -/// newtype_index! { -/// pub struct MyIdx {} -/// } -/// -/// let my_index_vec: IndexVec = IndexVec::from_raw(vec![0,1,2,3]); -/// let idx: MyIdx = MyIdx::from_u32(2); -/// assert_eq!(my_index_vec[idx], 2); -/// ``` /// /// [`newtype_index!`]: ../macro.newtype_index.html #[derive(Clone, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct IndexVec { pub raw: Vec, - _marker: PhantomData, + _marker: PhantomData, } impl IndexVec { @@ -77,7 +65,7 @@ impl IndexVec { IndexVec::from_raw(vec![elem; universe.len()]) } - /// Creates a new `IndexVec` with n copies of `elem` + /// Creates a new IndexVec #[inline] pub fn from_elem_n(elem: T, n: usize) -> Self where From c8875309b8865b0fc119da4ba795dae129532bc1 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 10 Jan 2024 17:12:01 +0200 Subject: [PATCH 056/676] deps: deduplicate the version of libloading used The changelog can be found here: https://docs.rs/libloading/latest/libloading/changelog/r0_8_0/index.html --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fdac789423c9c..c57e964168f4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" -libloading = { version = "0.7.3", optional = true } +libloading = { version = "0.8.0", optional = true } smallvec = "1.8.1" [patch.crates-io] From be1b86fef43a7cf6c57a2848be02e0dca4738ef1 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 10 Jan 2024 17:13:03 +0200 Subject: [PATCH 057/676] Format sources into the error message when loading codegen backends cc https://github.com/rust-lang/rustc_codegen_cranelift/issues/1447 --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74e7afee7bcb2..6d6a1200f5028 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -246,12 +246,12 @@ checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys", ] [[package]] From ee8510e4e13e723639e904cdc218e6f3013f0bb4 Mon Sep 17 00:00:00 2001 From: ardi Date: Wed, 10 Jan 2024 18:28:42 +0100 Subject: [PATCH 058/676] Fix some mistakes + new doc --- compiler/rustc_index/src/vec.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 3c66e6dde1c2e..73265eb89961c 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -17,15 +17,13 @@ use crate::{Idx, IndexSlice}; /// While it's possible to use `u32` or `usize` directly for `I`, /// you almost certainly want to use a [`newtype_index!`]-generated type instead. /// -/// This allows to index the IndexVec with the new index type -/// -/// +/// This allows to index the IndexVec with the new index type. /// [`newtype_index!`]: ../macro.newtype_index.html #[derive(Clone, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct IndexVec { pub raw: Vec, - _marker: PhantomData, + _marker: PhantomData, } impl IndexVec { @@ -35,7 +33,7 @@ impl IndexVec { IndexVec::from_raw(Vec::new()) } - /// Constructs a new `IndexVec` from a `Vec` + /// Constructs a new `IndexVec` from a `Vec`. #[inline] pub const fn from_raw(raw: Vec) -> Self { IndexVec { raw, _marker: PhantomData } @@ -65,7 +63,7 @@ impl IndexVec { IndexVec::from_raw(vec![elem; universe.len()]) } - /// Creates a new IndexVec + /// Creates a new IndexVec with n copies of the `elem`. #[inline] pub fn from_elem_n(elem: T, n: usize) -> Self where @@ -92,6 +90,7 @@ impl IndexVec { IndexSlice::from_raw_mut(&mut self.raw) } + /// Pushes an element to the array returning the index where it was pushed to. #[inline] pub fn push(&mut self, d: T) -> I { let idx = self.next_index(); From b0dc5439197cfe17d398e3da5951d47e0add8ec9 Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Thu, 11 Jan 2024 04:53:55 +0000 Subject: [PATCH 059/676] 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 bdf2416a20e61..61aa9c128220d 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -94807670a6a3834cc9b71b0b803d49d307c9ba5d +65b323b168daa6c723a8a5b4ddf939f3b12e0329 From 7c389acd277eada4d2e0856707361cce24c9b23f Mon Sep 17 00:00:00 2001 From: cocodery Date: Thu, 11 Jan 2024 14:52:03 +0800 Subject: [PATCH 060/676] Fix error warning span for issue12045 --- clippy_lints/src/no_effect.rs | 2 +- tests/ui/no_effect.stderr | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 6bbe427ea2988..2a2c2b331ba79 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -155,7 +155,7 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { cx, NO_EFFECT_UNDERSCORE_BINDING, init.hir_id, - stmt.span, + ident.span, "binding to `_` prefixed variable with no side-effect", ); return true; diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index f5ba234b4cbf6..8140ba1feee9c 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -152,31 +152,31 @@ LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:175:5 + --> $DIR/no_effect.rs:175:9 | LL | let _unused = 1; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^ | = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::no_effect_underscore_binding)]` error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:178:5 + --> $DIR/no_effect.rs:178:9 | LL | let _penguin = || println!("Some helpful closure"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:180:5 + --> $DIR/no_effect.rs:180:9 | LL | let _duck = Struct { field: 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:182:5 + --> $DIR/no_effect.rs:182:9 | LL | let _cat = [2, 4, 6, 8][2]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 29 previous errors From fb83ef649587413c4e3a8ec9e364b828ec250a56 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 11 Jan 2024 14:22:44 +1100 Subject: [PATCH 061/676] Stop using `DiagnosticBuilder::buffer` in the parser. One consequence is that errors returned by `maybe_new_parser_from_source_str` now must be consumed, so a bunch of places that previously ignored those errors now cancel them. (Most of them explicitly dropped the errors before. I guess that was to indicate "we are explicitly ignoring these", though I'm not 100% sure.) --- clippy_lints/src/doc/needless_doctest_main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/doc/needless_doctest_main.rs b/clippy_lints/src/doc/needless_doctest_main.rs index a744b69ecb478..8b018220c1715 100644 --- a/clippy_lints/src/doc/needless_doctest_main.rs +++ b/clippy_lints/src/doc/needless_doctest_main.rs @@ -53,7 +53,7 @@ pub fn check( let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) { Ok(p) => p, Err(errs) => { - drop(errs); + errs.into_iter().for_each(|err| err.cancel()); return (false, test_attr_spans); }, }; From aa220c7ee7a51ab39bccd03ee90fa1c9365a589a Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 11 Jan 2024 17:27:03 +0100 Subject: [PATCH 062/676] Merge commit '26ac6aab023393c94edf42f38f6ad31196009643' --- .github/workflows/clippy.yml | 2 +- .github/workflows/clippy_bors.yml | 10 +- .github/workflows/clippy_dev.yml | 2 +- .github/workflows/deploy.yml | 4 +- .github/workflows/remark.yml | 2 +- CHANGELOG.md | 7 + COPYRIGHT | 2 +- LICENSE-APACHE | 2 +- LICENSE-MIT | 2 +- README.md | 4 +- book/src/README.md | 2 +- book/src/SUMMARY.md | 1 + .../continuous_integration/github_actions.md | 2 +- book/src/continuous_integration/gitlab.md | 16 + book/src/development/macro_expansions.md | 2 +- book/src/development/type_checking.md | 4 +- book/src/lint_configuration.md | 10 + clippy_config/src/conf.rs | 7 +- clippy_config/src/metadata.rs | 3 + clippy_config/src/msrvs.rs | 2 +- clippy_config/src/types.rs | 6 + clippy_dev/src/new_lint.rs | 2 +- clippy_lints/src/casts/cast_sign_loss.rs | 141 ++++-- clippy_lints/src/declared_lints.rs | 8 +- clippy_lints/src/default_numeric_fallback.rs | 41 +- ...ith_brackets.rs => empty_with_brackets.rs} | 56 ++- clippy_lints/src/if_then_some_else_none.rs | 7 +- clippy_lints/src/instant_subtraction.rs | 5 +- clippy_lints/src/item_name_repetitions.rs | 5 + clippy_lints/src/iter_without_into_iter.rs | 9 +- clippy_lints/src/lib.rs | 17 +- clippy_lints/src/lines_filter_map_ok.rs | 3 +- clippy_lints/src/methods/filter_map.rs | 3 +- clippy_lints/src/methods/iter_filter.rs | 206 +++++++-- .../src/methods/manual_is_variant_and.rs | 59 +++ clippy_lints/src/methods/map_clone.rs | 142 ++++-- clippy_lints/src/methods/mod.rs | 115 ++++- .../src/methods/option_as_ref_cloned.rs | 24 + .../src/methods/option_map_unwrap_or.rs | 2 +- .../src/methods/path_ends_with_ext.rs | 2 +- clippy_lints/src/methods/redundant_as_str.rs | 6 +- clippy_lints/src/methods/str_split.rs | 38 ++ .../src/methods/unnecessary_to_owned.rs | 24 +- clippy_lints/src/methods/useless_asref.rs | 123 +++++- clippy_lints/src/methods/utils.rs | 1 + .../src/missing_asserts_for_indexing.rs | 2 +- .../src/missing_enforced_import_rename.rs | 14 +- clippy_lints/src/mutex_atomic.rs | 26 +- clippy_lints/src/no_effect.rs | 2 +- .../src/non_octal_unix_permissions.rs | 12 +- clippy_lints/src/operators/identity_op.rs | 208 +++++---- clippy_lints/src/pub_underscore_fields.rs | 83 ++++ clippy_lints/src/question_mark.rs | 7 +- clippy_lints/src/serde_api.rs | 2 +- ...ead_local_initializer_can_be_made_const.rs | 102 +++++ clippy_lints/src/transmute/eager_transmute.rs | 53 ++- .../src/transmute/transmute_undefined_repr.rs | 4 +- clippy_lints/src/unconditional_recursion.rs | 413 +++++++++++++++--- .../src/undocumented_unsafe_blocks.rs | 10 +- clippy_lints/src/unit_types/let_unit_value.rs | 21 +- clippy_lints/src/vec.rs | 17 +- clippy_lints/src/wildcard_imports.rs | 2 +- clippy_utils/src/eager_or_lazy.rs | 13 +- clippy_utils/src/hir_utils.rs | 2 +- clippy_utils/src/macros.rs | 2 +- clippy_utils/src/ty/type_certainty/mod.rs | 6 +- rust-toolchain | 2 +- rustc_tools_util/README.md | 2 +- .../all_pub_fields/clippy.toml | 1 + .../exported/clippy.toml | 1 + ...ub_underscore_fields.all_pub_fields.stderr | 60 +++ .../pub_underscore_fields.exported.stderr | 12 + .../pub_underscore_fields.rs | 66 +++ .../toml_unknown_key/conf_unknown_key.stderr | 2 + tests/ui/as_conversions.rs | 2 +- tests/ui/cast.rs | 49 +++ tests/ui/cast.stderr | 74 +++- tests/ui/crashes/ice-8821.fixed | 10 - tests/ui/crashes/ice-8821.rs | 2 - tests/ui/crashes/ice-8821.stderr | 11 - tests/ui/default_numeric_fallback_f64.fixed | 4 +- tests/ui/default_numeric_fallback_f64.rs | 2 - tests/ui/default_numeric_fallback_f64.stderr | 26 +- tests/ui/default_numeric_fallback_i32.fixed | 36 +- tests/ui/default_numeric_fallback_i32.rs | 34 +- tests/ui/default_numeric_fallback_i32.stderr | 44 +- tests/ui/eager_transmute.fixed | 35 +- tests/ui/eager_transmute.rs | 35 +- tests/ui/eager_transmute.stderr | 117 ++++- .../empty_enum_variants_with_brackets.fixed | 27 ++ tests/ui/empty_enum_variants_with_brackets.rs | 27 ++ .../empty_enum_variants_with_brackets.stderr | 36 ++ tests/ui/identity_op.fixed | 94 +++- tests/ui/identity_op.rs | 94 +++- tests/ui/identity_op.stderr | 154 +++++-- tests/ui/if_then_some_else_none.rs | 5 + tests/ui/into_iter_without_iter.rs | 39 ++ tests/ui/into_iter_without_iter.stderr | 38 +- tests/ui/iter_filter_is_ok.fixed | 193 +++++++- tests/ui/iter_filter_is_ok.rs | 193 +++++++- tests/ui/iter_filter_is_ok.stderr | 74 +++- tests/ui/iter_filter_is_some.fixed | 231 +++++++++- tests/ui/iter_filter_is_some.rs | 231 +++++++++- tests/ui/iter_filter_is_some.stderr | 62 ++- tests/ui/iter_without_into_iter.rs | 31 ++ tests/ui/iter_without_into_iter.stderr | 40 +- tests/ui/let_unit.fixed | 50 +-- tests/ui/let_unit.rs | 48 +- tests/ui/let_unit.stderr | 56 +-- tests/ui/manual_is_variant_and.fixed | 51 +++ tests/ui/manual_is_variant_and.rs | 57 +++ tests/ui/manual_is_variant_and.stderr | 82 ++++ tests/ui/map_clone.fixed | 24 + tests/ui/map_clone.rs | 24 + tests/ui/map_clone.stderr | 44 +- tests/ui/must_use_candidates.fixed | 6 +- tests/ui/must_use_candidates.rs | 6 +- tests/ui/must_use_candidates.stderr | 10 +- tests/ui/mutex_atomic.rs | 19 +- tests/ui/mutex_atomic.stderr | 30 +- tests/ui/non_octal_unix_permissions.fixed | 4 + tests/ui/non_octal_unix_permissions.rs | 4 + tests/ui/non_octal_unix_permissions.stderr | 2 +- tests/ui/option_as_ref_cloned.fixed | 21 + tests/ui/option_as_ref_cloned.rs | 21 + tests/ui/option_as_ref_cloned.stderr | 37 ++ tests/ui/redundant_as_str.fixed | 2 +- tests/ui/redundant_as_str.rs | 2 +- tests/ui/regex.rs | 2 +- tests/ui/single_char_pattern.fixed | 2 + tests/ui/single_char_pattern.rs | 2 + tests/ui/single_char_pattern.stderr | 26 +- tests/ui/str_split.fixed | 145 ++++++ tests/ui/str_split.rs | 145 ++++++ tests/ui/str_split.stderr | 65 +++ tests/ui/struct_fields.rs | 24 +- tests/ui/struct_fields.stderr | 28 +- ..._local_initializer_can_be_made_const.fixed | 30 ++ ...ead_local_initializer_can_be_made_const.rs | 30 ++ ...local_initializer_can_be_made_const.stderr | 29 ++ tests/ui/unconditional_recursion.rs | 108 ++++- tests/ui/unconditional_recursion.stderr | 95 +++- tests/ui/unnecessary_lazy_eval.fixed | 13 + tests/ui/unnecessary_lazy_eval.rs | 13 + tests/ui/unnecessary_lazy_eval.stderr | 126 +++--- tests/ui/unnecessary_safety_comment.rs | 21 + tests/ui/unnecessary_to_owned_on_split.fixed | 18 +- tests/ui/unnecessary_to_owned_on_split.rs | 18 +- tests/ui/unnecessary_to_owned_on_split.stderr | 24 +- tests/ui/useless_asref.fixed | 14 +- tests/ui/useless_asref.rs | 14 +- tests/ui/useless_asref.stderr | 42 +- tests/ui/useless_conversion.fixed | 4 +- tests/ui/useless_conversion.rs | 4 +- tests/ui/vec.fixed | 7 + tests/ui/vec.rs | 7 + triagebot.toml | 1 - 157 files changed, 5166 insertions(+), 819 deletions(-) create mode 100644 book/src/continuous_integration/gitlab.md rename clippy_lints/src/{empty_structs_with_brackets.rs => empty_with_brackets.rs} (62%) create mode 100644 clippy_lints/src/methods/manual_is_variant_and.rs create mode 100644 clippy_lints/src/methods/option_as_ref_cloned.rs create mode 100644 clippy_lints/src/methods/str_split.rs create mode 100644 clippy_lints/src/pub_underscore_fields.rs create mode 100644 clippy_lints/src/thread_local_initializer_can_be_made_const.rs create mode 100644 tests/ui-toml/pub_underscore_fields/all_pub_fields/clippy.toml create mode 100644 tests/ui-toml/pub_underscore_fields/exported/clippy.toml create mode 100644 tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr create mode 100644 tests/ui-toml/pub_underscore_fields/pub_underscore_fields.exported.stderr create mode 100644 tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs delete mode 100644 tests/ui/crashes/ice-8821.fixed delete mode 100644 tests/ui/crashes/ice-8821.stderr create mode 100644 tests/ui/empty_enum_variants_with_brackets.fixed create mode 100644 tests/ui/empty_enum_variants_with_brackets.rs create mode 100644 tests/ui/empty_enum_variants_with_brackets.stderr create mode 100644 tests/ui/manual_is_variant_and.fixed create mode 100644 tests/ui/manual_is_variant_and.rs create mode 100644 tests/ui/manual_is_variant_and.stderr create mode 100644 tests/ui/option_as_ref_cloned.fixed create mode 100644 tests/ui/option_as_ref_cloned.rs create mode 100644 tests/ui/option_as_ref_cloned.stderr create mode 100644 tests/ui/str_split.fixed create mode 100644 tests/ui/str_split.rs create mode 100644 tests/ui/str_split.stderr create mode 100644 tests/ui/thread_local_initializer_can_be_made_const.fixed create mode 100644 tests/ui/thread_local_initializer_can_be_made_const.rs create mode 100644 tests/ui/thread_local_initializer_can_be_made_const.stderr diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 99d80bec0255f..5ba960db66dde 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -38,7 +38,7 @@ jobs: github_token: "${{ secrets.github_token }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install toolchain run: rustup show active-toolchain diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 73c2555074286..012797e5ca72a 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -26,7 +26,7 @@ jobs: github_token: "${{ secrets.github_token }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.ref }} @@ -72,7 +72,7 @@ jobs: github_token: "${{ secrets.github_token }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install i686 dependencies if: matrix.host == 'i686-unknown-linux-gnu' @@ -151,7 +151,7 @@ jobs: github_token: "${{ secrets.github_token }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install toolchain run: rustup show active-toolchain @@ -175,7 +175,7 @@ jobs: github_token: "${{ secrets.github_token }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install toolchain run: rustup show active-toolchain @@ -231,7 +231,7 @@ jobs: github_token: "${{ secrets.github_token }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install toolchain run: rustup show active-toolchain diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml index 0f0e3f2db925c..37f18a4c08740 100644 --- a/.github/workflows/clippy_dev.yml +++ b/.github/workflows/clippy_dev.yml @@ -24,7 +24,7 @@ jobs: steps: # Setup - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run - name: Build diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 999ee7acfe761..94f494b65c47c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -21,10 +21,10 @@ jobs: steps: # Setup - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ env.TARGET_BRANCH }} path: 'out' diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml index 30bd476332f75..05e1b3b9202b4 100644 --- a/.github/workflows/remark.yml +++ b/.github/workflows/remark.yml @@ -16,7 +16,7 @@ jobs: steps: # Setup - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index f82421a687b82..4d32bbec914a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5105,6 +5105,7 @@ Released 2018-09-13 [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop [`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum +[`empty_enum_variants_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum_variants_with_brackets [`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments [`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr [`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop @@ -5294,6 +5295,7 @@ Released 2018-09-13 [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check [`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite [`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite +[`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and [`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map @@ -5440,6 +5442,7 @@ Released 2018-09-13 [`only_used_in_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#only_used_in_recursion [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref [`option_and_then_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_and_then_some +[`option_as_ref_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_cloned [`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref [`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap [`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used @@ -5483,6 +5486,7 @@ Released 2018-09-13 [`ptr_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq [`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names +[`pub_underscore_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields [`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use [`pub_with_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_with_shorthand [`pub_without_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_without_shorthand @@ -5580,6 +5584,7 @@ Released 2018-09-13 [`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive [`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc [`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core +[`str_split_at_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_split_at_newline [`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string [`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add [`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign @@ -5612,6 +5617,7 @@ Released 2018-09-13 [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr [`test_attr_in_doctest`]: https://rust-lang.github.io/rust-clippy/master/index.html#test_attr_in_doctest [`tests_outside_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#tests_outside_test_module +[`thread_local_initializer_can_be_made_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#thread_local_initializer_can_be_made_const [`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some [`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display [`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args @@ -5810,4 +5816,5 @@ Released 2018-09-13 [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles [`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items +[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior diff --git a/COPYRIGHT b/COPYRIGHT index 82703b18fd7d2..219693d63d973 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,6 +1,6 @@ // REUSE-IgnoreStart -Copyright 2014-2022 The Rust Project Developers +Copyright 2014-2024 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 0d62c37278e58..506582c31d6d5 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2014-2022 The Rust Project Developers +Copyright 2014-2024 The Rust Project Developers Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/LICENSE-MIT b/LICENSE-MIT index b724b24aa8309..6d8ee9afb6163 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2014-2022 The Rust Project Developers +Copyright (c) 2014-2024 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/README.md b/README.md index 5d490645d8979..fa18447090c19 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 650 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. @@ -278,7 +278,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT -Copyright 2014-2023 The Rust Project Developers +Copyright 2014-2024 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/book/src/README.md b/book/src/README.md index 486ea3df70420..e7972b0db19ce 100644 --- a/book/src/README.md +++ b/book/src/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 650 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index b02457307d743..a048fbbd8acf9 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -9,6 +9,7 @@ - [Clippy's Lints](lints.md) - [Continuous Integration](continuous_integration/README.md) - [GitHub Actions](continuous_integration/github_actions.md) + - [GitLab CI](continuous_integration/gitlab.md) - [Travis CI](continuous_integration/travis.md) - [Development](development/README.md) - [Basics](development/basics.md) diff --git a/book/src/continuous_integration/github_actions.md b/book/src/continuous_integration/github_actions.md index 339287a7dd95f..b588c8f0f02c4 100644 --- a/book/src/continuous_integration/github_actions.md +++ b/book/src/continuous_integration/github_actions.md @@ -15,7 +15,7 @@ jobs: clippy_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run Clippy run: cargo clippy --all-targets --all-features ``` diff --git a/book/src/continuous_integration/gitlab.md b/book/src/continuous_integration/gitlab.md new file mode 100644 index 0000000000000..bb3ef246c2faa --- /dev/null +++ b/book/src/continuous_integration/gitlab.md @@ -0,0 +1,16 @@ +# GitLab CI + +You can add Clippy to GitLab CI by using the latest stable [rust docker image](https://hub.docker.com/_/rust), +as it is shown in the `.gitlab-ci.yml` CI configuration file below, + +```yml +# Make sure CI fails on all warnings, including Clippy lints +variables: + RUSTFLAGS: "-Dwarnings" + +clippy_check: + image: rust:latest + script: + - rustup component add clippy + - cargo clippy --all-targets --all-features +``` diff --git a/book/src/development/macro_expansions.md b/book/src/development/macro_expansions.md index c5eb000272d39..aecca9ef72e98 100644 --- a/book/src/development/macro_expansions.md +++ b/book/src/development/macro_expansions.md @@ -102,7 +102,7 @@ let x: Option = Some(42); m!(x, x.unwrap()); ``` -If the `m!(x, x.unwrapp());` line is expanded, we would get two expanded +If the `m!(x, x.unwrap());` line is expanded, we would get two expanded expressions: - `x.is_some()` (from the `$a.is_some()` line in the `m` macro) diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index a8c9660da4c85..dc29ab5d08dad 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -133,7 +133,7 @@ in this chapter: - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html) - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html) -[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Adt +[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html#variant.Adt [AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty [node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type @@ -144,7 +144,7 @@ in this chapter: [LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html [pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/typeck_results/struct.TypeckResults.html#method.pat_ty [Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html -[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html +[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html [middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html [hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 7c9a8eb1bfba1..3b62ae0524ab0 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -805,3 +805,13 @@ for _ in &mut *rmvec {} * [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc) +## `pub-underscore-fields-behavior` + + +**Default Value:** `"PublicallyExported"` + +--- +**Affected lints:** +* [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields) + + diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index a4f368397cede..5477d9b83a72c 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -1,5 +1,5 @@ use crate::msrvs::Msrv; -use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, Rename}; +use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename}; use crate::ClippyConfiguration; use rustc_data_structures::fx::FxHashSet; use rustc_session::Session; @@ -547,6 +547,11 @@ define_Conf! { /// /// Whether to also run the listed lints on private items. (check_private_items: bool = false), + /// Lint: PUB_UNDERSCORE_FIELDS + /// + /// Lint "public" fields in a struct that are prefixed with an underscore based on their + /// exported visibility, or whether they are marked as "pub". + (pub_underscore_fields_behavior: PubUnderscoreFieldsBehaviour = PubUnderscoreFieldsBehaviour::PublicallyExported), } /// Search for the configuration file. diff --git a/clippy_config/src/metadata.rs b/clippy_config/src/metadata.rs index 2451fbc91e898..3ba2796e18d3c 100644 --- a/clippy_config/src/metadata.rs +++ b/clippy_config/src/metadata.rs @@ -96,6 +96,9 @@ fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec, String)> { doc_comment.make_ascii_lowercase(); let lints: Vec = doc_comment .split_off(DOC_START.len()) + .lines() + .next() + .unwrap() .split(", ") .map(str::to_string) .collect(); diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index dae9f09ec00a0..72d5b9aff28df 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -17,7 +17,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } - 1,70,0 { OPTION_IS_SOME_AND, BINARY_HEAP_RETAIN } + 1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index df48cc3f5e391..baee09629ac44 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -126,3 +126,9 @@ unimplemented_serialize! { Rename, MacroMatcher, } + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)] +pub enum PubUnderscoreFieldsBehaviour { + PublicallyExported, + AllPubFields, +} diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 31a42734c1310..5d9cde06cd86b 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -67,7 +67,7 @@ pub fn create( if pass == "early" { println!( "\n\ - NOTE: Use a late pass unless you need something specific from\ + NOTE: Use a late pass unless you need something specific from\n\ an early pass, as they lack many features and utilities" ); } diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index bd12ee406284b..1df5a25f674d7 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -1,12 +1,14 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint; -use clippy_utils::{method_chain_args, sext}; -use rustc_hir::{Expr, ExprKind}; +use clippy_utils::{clip, method_chain_args, sext}; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, UintTy}; use super::CAST_SIGN_LOSS; +const METHODS_RET_POSITIVE: &[&str] = &["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"]; + pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { if should_lint(cx, cast_op, cast_from, cast_to) { span_lint( @@ -25,33 +27,28 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast return false; } - // Don't lint for positive constants. - let const_val = constant(cx, cx.typeck_results(), cast_op); - if let Some(Constant::Int(n)) = const_val - && let ty::Int(ity) = *cast_from.kind() - && sext(cx.tcx, n, ity) >= 0 - { + // Don't lint if `cast_op` is known to be positive. + if let Sign::ZeroOrPositive = expr_sign(cx, cast_op, cast_from) { return false; } - // Don't lint for the result of methods that always return non-negative values. - if let ExprKind::MethodCall(path, ..) = cast_op.kind { - let mut method_name = path.ident.name.as_str(); - let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"]; - - if method_name == "unwrap" - && let Some(arglist) = method_chain_args(cast_op, &["unwrap"]) - && let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind - { - method_name = inner_path.ident.name.as_str(); - } - - if allowed_methods.iter().any(|&name| method_name == name) { - return false; - } + let (mut uncertain_count, mut negative_count) = (0, 0); + // Peel off possible binary expressions, e.g. x * x * y => [x, x, y] + let Some(exprs) = exprs_with_selected_binop_peeled(cast_op) else { + // Assume cast sign lose if we cannot determine the sign of `cast_op` + return true; + }; + for expr in exprs { + let ty = cx.typeck_results().expr_ty(expr); + match expr_sign(cx, expr, ty) { + Sign::Negative => negative_count += 1, + Sign::Uncertain => uncertain_count += 1, + Sign::ZeroOrPositive => (), + }; } - true + // Lint if there are odd number of uncertain or negative results + uncertain_count % 2 == 1 || negative_count % 2 == 1 }, (false, true) => !cast_to.is_signed(), @@ -59,3 +56,97 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast (_, _) => false, } } + +fn get_const_int_eval(cx: &LateContext<'_>, expr: &Expr<'_>, ty: Ty<'_>) -> Option { + if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)? + && let ty::Int(ity) = *ty.kind() + { + return Some(sext(cx.tcx, n, ity)); + } + None +} + +enum Sign { + ZeroOrPositive, + Negative, + Uncertain, +} + +fn expr_sign(cx: &LateContext<'_>, expr: &Expr<'_>, ty: Ty<'_>) -> Sign { + // Try evaluate this expr first to see if it's positive + if let Some(val) = get_const_int_eval(cx, expr, ty) { + return if val >= 0 { Sign::ZeroOrPositive } else { Sign::Negative }; + } + // Calling on methods that always return non-negative values. + if let ExprKind::MethodCall(path, caller, args, ..) = expr.kind { + let mut method_name = path.ident.name.as_str(); + + if method_name == "unwrap" + && let Some(arglist) = method_chain_args(expr, &["unwrap"]) + && let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind + { + method_name = inner_path.ident.name.as_str(); + } + + if method_name == "pow" + && let [arg] = args + { + return pow_call_result_sign(cx, caller, arg); + } else if METHODS_RET_POSITIVE.iter().any(|&name| method_name == name) { + return Sign::ZeroOrPositive; + } + } + + Sign::Uncertain +} + +/// Return the sign of the `pow` call's result. +/// +/// If the caller is a positive number, the result is always positive, +/// If the `power_of` is a even number, the result is always positive as well, +/// Otherwise a [`Sign::Uncertain`] will be returned. +fn pow_call_result_sign(cx: &LateContext<'_>, caller: &Expr<'_>, power_of: &Expr<'_>) -> Sign { + let caller_ty = cx.typeck_results().expr_ty(caller); + if let Some(caller_val) = get_const_int_eval(cx, caller, caller_ty) + && caller_val >= 0 + { + return Sign::ZeroOrPositive; + } + + if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), power_of) + && clip(cx.tcx, n, UintTy::U32) % 2 == 0 + { + return Sign::ZeroOrPositive; + } + + Sign::Uncertain +} + +/// Peels binary operators such as [`BinOpKind::Mul`], [`BinOpKind::Div`] or [`BinOpKind::Rem`], +/// which the result could always be positive under certain condition. +/// +/// Other operators such as `+`/`-` causing the result's sign hard to determine, which we will +/// return `None` +fn exprs_with_selected_binop_peeled<'a>(expr: &'a Expr<'_>) -> Option>> { + #[inline] + fn collect_operands<'a>(expr: &'a Expr<'a>, operands: &mut Vec<&'a Expr<'a>>) -> Option<()> { + match expr.kind { + ExprKind::Binary(op, lhs, rhs) => { + if matches!(op.node, BinOpKind::Mul | BinOpKind::Div | BinOpKind::Rem) { + collect_operands(lhs, operands); + operands.push(rhs); + } else { + // Things are complicated when there are other binary ops exist, + // abort checking by returning `None` for now. + return None; + } + }, + _ => operands.push(expr), + } + Some(()) + } + + let mut res = vec![]; + collect_operands(expr, &mut res)?; + Some(res) +} diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index eae9dfac064e8..20230106d5366 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -150,7 +150,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO, crate::empty_drop::EMPTY_DROP_INFO, crate::empty_enum::EMPTY_ENUM_INFO, - crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO, + crate::empty_with_brackets::EMPTY_ENUM_VARIANTS_WITH_BRACKETS_INFO, + crate::empty_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO, crate::endian_bytes::BIG_ENDIAN_BYTES_INFO, crate::endian_bytes::HOST_ENDIAN_BYTES_INFO, crate::endian_bytes::LITTLE_ENDIAN_BYTES_INFO, @@ -385,6 +386,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::JOIN_ABSOLUTE_PATHS_INFO, crate::methods::MANUAL_FILTER_MAP_INFO, crate::methods::MANUAL_FIND_MAP_INFO, + crate::methods::MANUAL_IS_VARIANT_AND_INFO, crate::methods::MANUAL_NEXT_BACK_INFO, crate::methods::MANUAL_OK_OR_INFO, crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO, @@ -408,6 +410,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::NO_EFFECT_REPLACE_INFO, crate::methods::OBFUSCATED_IF_ELSE_INFO, crate::methods::OK_EXPECT_INFO, + crate::methods::OPTION_AS_REF_CLONED_INFO, crate::methods::OPTION_AS_REF_DEREF_INFO, crate::methods::OPTION_FILTER_MAP_INFO, crate::methods::OPTION_MAP_OR_ERR_OK_INFO, @@ -433,6 +436,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::STABLE_SORT_PRIMITIVE_INFO, crate::methods::STRING_EXTEND_CHARS_INFO, crate::methods::STRING_LIT_CHARS_ANY_INFO, + crate::methods::STR_SPLIT_AT_NEWLINE_INFO, crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO, crate::methods::SUSPICIOUS_MAP_INFO, crate::methods::SUSPICIOUS_SPLITN_INFO, @@ -576,6 +580,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::ptr::MUT_FROM_REF_INFO, crate::ptr::PTR_ARG_INFO, crate::ptr_offset_with_cast::PTR_OFFSET_WITH_CAST_INFO, + crate::pub_underscore_fields::PUB_UNDERSCORE_FIELDS_INFO, crate::pub_use::PUB_USE_INFO, crate::question_mark::QUESTION_MARK_INFO, crate::question_mark_used::QUESTION_MARK_USED_INFO, @@ -648,6 +653,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::tabs_in_doc_comments::TABS_IN_DOC_COMMENTS_INFO, crate::temporary_assignment::TEMPORARY_ASSIGNMENT_INFO, crate::tests_outside_test_module::TESTS_OUTSIDE_TEST_MODULE_INFO, + crate::thread_local_initializer_can_be_made_const::THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST_INFO, crate::to_digit_is_some::TO_DIGIT_IS_SOME_INFO, crate::trailing_empty_array::TRAILING_EMPTY_ARRAY_INFO, crate::trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS_INFO, diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs index 64a924a776a65..712bc075650fa 100644 --- a/clippy_lints/src/default_numeric_fallback.rs +++ b/clippy_lints/src/default_numeric_fallback.rs @@ -4,7 +4,7 @@ use clippy_utils::{get_parent_node, numeric_literal}; use rustc_ast::ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind}; +use rustc_hir::{Block, Body, Expr, ExprKind, FnRetTy, HirId, ItemKind, Lit, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty}; @@ -122,13 +122,42 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { match &expr.kind { + ExprKind::Block( + Block { + stmts, expr: Some(_), .. + }, + _, + ) => { + if let Some(parent) = self.cx.tcx.hir().find_parent(expr.hir_id) + && let Some(fn_sig) = parent.fn_sig() + && let FnRetTy::Return(_ty) = fn_sig.decl.output + { + // We cannot check the exact type since it's a `hir::Ty`` which does not implement `is_numeric` + self.ty_bounds.push(ExplicitTyBound(true)); + for stmt in *stmts { + self.visit_stmt(stmt); + } + self.ty_bounds.pop(); + // Ignore return expr since we know its type was inferred from return ty + return; + } + }, + + // Ignore return expr since we know its type was inferred from return ty + ExprKind::Ret(_) => return, + ExprKind::Call(func, args) => { if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) { for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) { - // Push found arg type, then visit arg. - self.ty_bounds.push((*bound).into()); - self.visit_expr(expr); - self.ty_bounds.pop(); + // If is from macro, try to use last bound type (typically pushed when visiting stmt), + // otherwise push found arg type, then visit arg, + if expr.span.from_expansion() { + self.visit_expr(expr); + } else { + self.ty_bounds.push((*bound).into()); + self.visit_expr(expr); + self.ty_bounds.pop(); + } } return; } @@ -137,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { ExprKind::MethodCall(_, receiver, args, _) => { if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) { let fn_sig = self.cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder(); - for (expr, bound) in iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) { + for (expr, bound) in iter::zip(iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) { self.ty_bounds.push((*bound).into()); self.visit_expr(expr); self.ty_bounds.pop(); diff --git a/clippy_lints/src/empty_structs_with_brackets.rs b/clippy_lints/src/empty_with_brackets.rs similarity index 62% rename from clippy_lints/src/empty_structs_with_brackets.rs rename to clippy_lints/src/empty_with_brackets.rs index 3cf67b3ecbfa4..969df6d85b5a0 100644 --- a/clippy_lints/src/empty_structs_with_brackets.rs +++ b/clippy_lints/src/empty_with_brackets.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; -use rustc_ast::ast::{Item, ItemKind, VariantData}; +use rustc_ast::ast::{Item, ItemKind, Variant, VariantData}; use rustc_errors::Applicability; use rustc_lexer::TokenKind; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -27,9 +27,38 @@ declare_clippy_lint! { restriction, "finds struct declarations with empty brackets" } -declare_lint_pass!(EmptyStructsWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS]); -impl EarlyLintPass for EmptyStructsWithBrackets { +declare_clippy_lint! { + /// ### What it does + /// Finds enum variants without fields that are declared with empty brackets. + /// + /// ### Why is this bad? + /// Empty brackets while defining enum variants are redundant and can be omitted. + /// + /// ### Example + /// ```no_run + /// enum MyEnum { + /// HasData(u8), + /// HasNoData(), // redundant parentheses + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// enum MyEnum { + /// HasData(u8), + /// HasNoData, + /// } + /// ``` + #[clippy::version = "1.77.0"] + pub EMPTY_ENUM_VARIANTS_WITH_BRACKETS, + restriction, + "finds enum variants with empty brackets" +} + +declare_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM_VARIANTS_WITH_BRACKETS]); + +impl EarlyLintPass for EmptyWithBrackets { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { let span_after_ident = item.span.with_lo(item.ident.span.hi()); @@ -53,6 +82,27 @@ impl EarlyLintPass for EmptyStructsWithBrackets { ); } } + + fn check_variant(&mut self, cx: &EarlyContext<'_>, variant: &Variant) { + let span_after_ident = variant.span.with_lo(variant.ident.span.hi()); + + if has_brackets(&variant.data) && has_no_fields(cx, &variant.data, span_after_ident) { + span_lint_and_then( + cx, + EMPTY_ENUM_VARIANTS_WITH_BRACKETS, + span_after_ident, + "enum variant has empty brackets", + |diagnostic| { + diagnostic.span_suggestion_hidden( + span_after_ident, + "remove the brackets", + "", + Applicability::MaybeIncorrect, + ); + }, + ); + } + } } fn has_no_ident_token(braces_span_str: &str) -> bool { diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs index cd6c46a71a8e1..8f48941c4a91e 100644 --- a/clippy_lints/src/if_then_some_else_none.rs +++ b/clippy_lints/src/if_then_some_else_none.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::eager_or_lazy::switch_to_eager_eval; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::Sugg; -use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks}; +use clippy_utils::{contains_return, higher, in_constant, is_else_clause, is_res_lang_ctor, path_res, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Expr, ExprKind}; @@ -74,6 +74,11 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { return; } + // `bool::then()` and `bool::then_some()` are not const + if in_constant(cx, expr.hir_id) { + return; + } + let ctxt = expr.span.ctxt(); if let Some(higher::If { diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs index 655f4b82aa4f1..17b6256f982b2 100644 --- a/clippy_lints/src/instant_subtraction.rs +++ b/clippy_lints/src/instant_subtraction.rs @@ -40,7 +40,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Lints subtraction between an [`Instant`] and a [`Duration`]. + /// Lints subtraction between an `Instant` and a `Duration`. /// /// ### Why is this bad? /// Unchecked subtraction could cause underflow on certain platforms, leading to @@ -57,9 +57,6 @@ declare_clippy_lint! { /// # use std::time::{Instant, Duration}; /// let time_passed = Instant::now().checked_sub(Duration::from_secs(5)); /// ``` - /// - /// [`Duration`]: std::time::Duration - /// [`Instant::now()`]: std::time::Instant::now; #[clippy::version = "1.67.0"] pub UNCHECKED_DURATION_SUBTRACTION, pedantic, diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index a9f1612ff05ed..276c1abb60cd5 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -1,6 +1,7 @@ //! lint on enum variants that are prefixed or suffixed by the same characters use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir}; +use clippy_utils::is_bool; use clippy_utils::macros::span_is_local; use clippy_utils::source::is_present_in_source; use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case}; @@ -231,6 +232,10 @@ fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: & (false, _) => ("pre", prefix), (true, false) => ("post", postfix), }; + if fields.iter().all(|field| is_bool(field.ty)) { + // If all fields are booleans, we don't want to emit this lint. + return; + } span_lint_and_help( cx, STRUCT_FIELD_NAMES, diff --git a/clippy_lints/src/iter_without_into_iter.rs b/clippy_lints/src/iter_without_into_iter.rs index c9dc48668f29d..903d3a2ab8960 100644 --- a/clippy_lints/src/iter_without_into_iter.rs +++ b/clippy_lints/src/iter_without_into_iter.rs @@ -5,7 +5,8 @@ use clippy_utils::ty::{implements_trait, make_normalized_projection}; use rustc_ast::Mutability; use rustc_errors::Applicability; use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; use rustc_session::declare_lint_pass; use rustc_span::{sym, Symbol}; @@ -152,7 +153,8 @@ fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol impl LateLintPass<'_> for IterWithoutIntoIter { fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { - if let ItemKind::Impl(imp) = item.kind + if !in_external_macro(cx.sess(), item.span) + && let ItemKind::Impl(imp) = item.kind && let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind && let Some(trait_ref) = imp.of_trait && trait_ref @@ -219,7 +221,8 @@ impl {self_ty_without_ref} {{ _ => return, }; - if let ImplItemKind::Fn(sig, _) = item.kind + if !in_external_macro(cx.sess(), item.span) + && let ImplItemKind::Fn(sig, _) = item.kind && let FnRetTy::Return(ret) = sig.decl.output && is_nameable_in_impl_trait(ret) && cx.tcx.generics_of(item_did).params.is_empty() diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 755a4ff525d2e..efdd392594977 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -115,7 +115,7 @@ mod duplicate_mod; mod else_if_without_else; mod empty_drop; mod empty_enum; -mod empty_structs_with_brackets; +mod empty_with_brackets; mod endian_bytes; mod entry; mod enum_clike; @@ -272,6 +272,7 @@ mod permissions_set_readonly_false; mod precedence; mod ptr; mod ptr_offset_with_cast; +mod pub_underscore_fields; mod pub_use; mod question_mark; mod question_mark_used; @@ -322,6 +323,7 @@ mod swap_ptr_to_ref; mod tabs_in_doc_comments; mod temporary_assignment; mod tests_outside_test_module; +mod thread_local_initializer_can_be_made_const; mod to_digit_is_some; mod trailing_empty_array; mod trait_bounds; @@ -571,6 +573,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { verbose_bit_mask_threshold, warn_on_all_wildcard_imports, check_private_items, + pub_underscore_fields_behavior, blacklisted_names: _, cyclomatic_complexity_threshold: _, @@ -947,7 +950,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { }) }); store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef)); - store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets)); + store.register_early_pass(|| Box::new(empty_with_brackets::EmptyWithBrackets)); store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings)); store.register_early_pass(|| Box::new(pub_use::PubUse)); store.register_late_pass(|_| Box::new(format_push_string::FormatPushString)); @@ -1080,7 +1083,15 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(repeat_vec_with_capacity::RepeatVecWithCapacity)); store.register_late_pass(|_| Box::new(uninhabited_references::UninhabitedReferences)); store.register_late_pass(|_| Box::new(ineffective_open_options::IneffectiveOpenOptions)); - store.register_late_pass(|_| Box::new(unconditional_recursion::UnconditionalRecursion)); + store.register_late_pass(|_| Box::::default()); + store.register_late_pass(move |_| { + Box::new(pub_underscore_fields::PubUnderscoreFields { + behavior: pub_underscore_fields_behavior, + }) + }); + store.register_late_pass(move |_| { + Box::new(thread_local_initializer_can_be_made_const::ThreadLocalInitializerCanBeMadeConst::new(msrv())) + }); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/lines_filter_map_ok.rs b/clippy_lints/src/lines_filter_map_ok.rs index 8a0955147bb54..29957e423b0b9 100644 --- a/clippy_lints/src/lines_filter_map_ok.rs +++ b/clippy_lints/src/lines_filter_map_ok.rs @@ -96,8 +96,7 @@ fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_str: &str) -> boo ExprKind::Path(qpath) => cx .qpath_res(qpath, fm_arg.hir_id) .opt_def_id() - .map(|did| match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)) - .unwrap_or_default(), + .is_some_and(|did| match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)), // Detect `|x| x.ok()` ExprKind::Closure(Closure { body, .. }) => { if let Body { diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs index 7cfd3d346b638..e489899c19e34 100644 --- a/clippy_lints/src/methods/filter_map.rs +++ b/clippy_lints/src/methods/filter_map.rs @@ -26,13 +26,14 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> hir::ExprKind::Closure(&hir::Closure { body, .. }) => { let body = cx.tcx.hir().body(body); let closure_expr = peel_blocks(body.value); - let arg_id = body.params[0].pat.hir_id; match closure_expr.kind { hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => { if ident.name == method_name && let hir::ExprKind::Path(path) = &receiver.kind && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id) + && !body.params.is_empty() { + let arg_id = body.params[0].pat.hir_id; return arg_id == *local; } false diff --git a/clippy_lints/src/methods/iter_filter.rs b/clippy_lints/src/methods/iter_filter.rs index ade8e3155fae3..9f84321ced4ae 100644 --- a/clippy_lints/src/methods/iter_filter.rs +++ b/clippy_lints/src/methods/iter_filter.rs @@ -1,87 +1,197 @@ +use clippy_utils::ty::get_iterator_item_ty; +use hir::ExprKind; use rustc_lint::{LateContext, LintContext}; use super::{ITER_FILTER_IS_OK, ITER_FILTER_IS_SOME}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, reindent_multiline}; -use clippy_utils::{is_trait_method, peel_blocks, span_contains_comment}; +use clippy_utils::{get_parent_expr, is_trait_method, peel_blocks, span_contains_comment}; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::def::Res; use rustc_hir::QPath; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use std::borrow::Cow; -fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool { - match &expr.kind { - hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name, - hir::ExprKind::Path(QPath::Resolved(_, segments)) => { - segments.segments.last().unwrap().ident.name == method_name +/// +/// Returns true if the expression is a method call to `method_name` +/// e.g. `a.method_name()` or `Option::method_name`. +/// +/// The type-checker verifies for us that the method accepts the right kind of items +/// (e.g. `Option::is_some` accepts `Option<_>`), so we don't need to check that. +/// +/// How to capture each case: +/// +/// `.filter(|a| { std::option::Option::is_some(a) })` +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- this is a closure, getting unwrapped and +/// recursively checked. +/// `std::option::Option::is_some(a)` +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- this is a call. It unwraps to a path with +/// `QPath::TypeRelative`. Since this is a type relative path, we need to check the method name, the +/// type, and that the parameter of the closure is passed in the call. This part is the dual of +/// `receiver.method_name()` below. +/// +/// `filter(std::option::Option::is_some);` +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- this is a type relative path, like above, we check the +/// type and the method name. +/// +/// `filter(|a| a.is_some());` +/// ^^^^^^^^^^^^^^^ <- this is a method call inside a closure, +/// we check that the parameter of the closure is the receiver of the method call and don't allow +/// any other parameters. +fn is_method( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + type_symbol: Symbol, + method_name: Symbol, + params: &[&hir::Pat<'_>], +) -> bool { + fn pat_is_recv(ident: Ident, param: &hir::Pat<'_>) -> bool { + match param.kind { + hir::PatKind::Binding(_, _, other, _) => ident == other, + hir::PatKind::Ref(pat, _) => pat_is_recv(ident, pat), + _ => false, + } + } + match expr.kind { + hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, recv, ..) => { + // compare the identifier of the receiver to the parameter + // we are in a filter => closure has a single parameter and a single, non-block + // expression, this means that the parameter shadows all outside variables with + // the same name => avoid FPs. If the parameter is not the receiver, then this hits + // outside variables => avoid FP + if ident.name == method_name + && let ExprKind::Path(QPath::Resolved(None, path)) = recv.kind + && let &[seg] = path.segments + && params.iter().any(|p| pat_is_recv(seg.ident, p)) + { + return true; + } + false + }, + // This is used to check for complete paths via `|a| std::option::Option::is_some(a)` + // this then unwraps to a path with `QPath::TypeRelative` + // we pass the params as they've been passed to the current call through the closure + hir::ExprKind::Call(expr, [param]) => { + // this will hit the `QPath::TypeRelative` case and check that the method name is correct + if is_method(cx, expr, type_symbol, method_name, params) + // we then check that this is indeed passing the parameter of the closure + && let ExprKind::Path(QPath::Resolved(None, path)) = param.kind + && let &[seg] = path.segments + && params.iter().any(|p| pat_is_recv(seg.ident, p)) + { + return true; + } + false + }, + hir::ExprKind::Path(QPath::TypeRelative(ty, mname)) => { + let ty = cx.typeck_results().node_type(ty.hir_id); + if let Some(did) = cx.tcx.get_diagnostic_item(type_symbol) + && ty.ty_adt_def() == cx.tcx.type_of(did).skip_binder().ty_adt_def() + { + return mname.ident.name == method_name; + } + false }, - hir::ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name, hir::ExprKind::Closure(&hir::Closure { body, .. }) => { let body = cx.tcx.hir().body(body); let closure_expr = peel_blocks(body.value); - let arg_id = body.params[0].pat.hir_id; - match closure_expr.kind { - hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => { - if ident.name == method_name - && let hir::ExprKind::Path(path) = &receiver.kind - && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id) - { - return arg_id == *local; - } - false - }, - _ => false, - } + let params = body.params.iter().map(|param| param.pat).collect::>(); + is_method(cx, closure_expr, type_symbol, method_name, params.as_slice()) }, _ => false, } } fn parent_is_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { - if let hir::Node::Expr(parent_expr) = cx.tcx.hir().get_parent(expr.hir_id) { - is_method(cx, parent_expr, rustc_span::sym::map) - } else { - false + if let Some(expr) = get_parent_expr(cx, expr) + && is_trait_method(cx, expr, sym::Iterator) + && let hir::ExprKind::MethodCall(path, _, _, _) = expr.kind + && path.ident.name == rustc_span::sym::map + { + return true; } + false } -#[allow(clippy::too_many_arguments)] -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_arg: &hir::Expr<'_>, filter_span: Span) { - let is_iterator = is_trait_method(cx, expr, sym::Iterator); - let parent_is_not_map = !parent_is_map(cx, expr); +enum FilterType { + IsSome, + IsOk, +} - if is_iterator - && parent_is_not_map - && is_method(cx, filter_arg, sym!(is_some)) - && !span_contains_comment(cx.sess().source_map(), filter_span.with_hi(expr.span.hi())) +/// Returns the `FilterType` of the expression if it is a filter over an Iter() { LL | extern "C" { LL | static baz: *const A; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr index f1fe1a6002c93..98ffb4567f164 100644 --- a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -6,6 +6,8 @@ LL | fn f() { LL | extern "C" { LL | static a: *const T; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:9:22 @@ -14,6 +16,8 @@ LL | fn g() { | - type parameter from outer item LL | static a: *const T = Default::default(); | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:15:24 @@ -23,6 +27,8 @@ LL | fn h() { LL | extern "C" { LL | static a: [u8; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:21:20 @@ -31,6 +37,8 @@ LL | fn i() { | - const parameter from outer item LL | static a: [u8; N] = [0; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:21:29 @@ -39,6 +47,8 @@ LL | fn i() { | - const parameter from outer item LL | static a: [u8; N] = [0; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error: aborting due to 5 previous errors From 2cfc81766c37eb0f6696d50f9207876293fa7732 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 13 Jan 2024 19:24:52 +0000 Subject: [PATCH 093/676] Special case 'generic param from outer item' message for `Self` --- compiler/rustc_resolve/messages.ftl | 10 ++++++++-- compiler/rustc_resolve/src/diagnostics.rs | 2 ++ compiler/rustc_resolve/src/errors.rs | 1 + tests/ui/error-codes/E0401.stderr | 4 ++-- tests/ui/resolve/issue-12796.rs | 2 +- tests/ui/resolve/issue-12796.stderr | 4 ++-- tests/ui/resolve/use-self-in-inner-fn.rs | 4 ++-- tests/ui/resolve/use-self-in-inner-fn.stderr | 4 ++-- 8 files changed, 20 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 1947107235b2c..69675b57e31a1 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -114,8 +114,14 @@ resolve_forward_declared_generic_param = .label = defaulted generic parameters cannot be forward declared resolve_generic_params_from_outer_item = - can't use generic parameters from outer item - .label = use of generic parameter from outer item + can't use {$is_self -> + [true] `Self` + *[false] generic parameters + } from outer item + .label = use of {$is_self -> + [true] `Self` + *[false] generic parameter + } from outer item .refer_to_type_directly = refer to the type directly here instead .suggestion = try introducing a local generic parameter here diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 46da5b9d2e46d..da31382112a0b 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -568,12 +568,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const), _ => None, }; + let is_self = matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }); let mut err = errs::GenericParamsFromOuterItem { span, label: None, refer_to_type_directly: None, sugg: None, static_or_const, + is_self, }; let sm = self.tcx.sess.source_map(); diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index bd00cab66b0aa..da89df84c8ae5 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -46,6 +46,7 @@ pub(crate) struct GenericParamsFromOuterItem { pub(crate) sugg: Option, #[subdiagnostic] pub(crate) static_or_const: Option, + pub(crate) is_self: bool, } #[derive(Subdiagnostic)] diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index d27fade487fe2..754867061c7f8 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -20,7 +20,7 @@ LL | fn baz $DIR/E0401.rs:24:25 | LL | impl Iterator for A { @@ -29,7 +29,7 @@ LL | impl Iterator for A { LL | fn helper(sel: &Self) -> u8 { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | refer to the type directly here instead error[E0283]: type annotations needed diff --git a/tests/ui/resolve/issue-12796.rs b/tests/ui/resolve/issue-12796.rs index de3e73437f080..e5dcf9643453b 100644 --- a/tests/ui/resolve/issue-12796.rs +++ b/tests/ui/resolve/issue-12796.rs @@ -1,7 +1,7 @@ trait Trait { fn outer(&self) { fn inner(_: &Self) { - //~^ ERROR can't use generic parameters from outer item + //~^ ERROR can't use `Self` from outer item } } } diff --git a/tests/ui/resolve/issue-12796.stderr b/tests/ui/resolve/issue-12796.stderr index 6809fd50f7475..2305971303a71 100644 --- a/tests/ui/resolve/issue-12796.stderr +++ b/tests/ui/resolve/issue-12796.stderr @@ -1,10 +1,10 @@ -error[E0401]: can't use generic parameters from outer item +error[E0401]: can't use `Self` from outer item --> $DIR/issue-12796.rs:3:22 | LL | fn inner(_: &Self) { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | can't use `Self` here error: aborting due to 1 previous error diff --git a/tests/ui/resolve/use-self-in-inner-fn.rs b/tests/ui/resolve/use-self-in-inner-fn.rs index f4dfa4c40ab24..62f9dc5664ffe 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.rs +++ b/tests/ui/resolve/use-self-in-inner-fn.rs @@ -4,8 +4,8 @@ impl A { //~^ NOTE `Self` type implicitly declared here, by this `impl` fn banana(&mut self) { fn peach(this: &Self) { - //~^ ERROR can't use generic parameters from outer item - //~| NOTE use of generic parameter from outer item + //~^ ERROR can't use `Self` from outer item + //~| NOTE use of `Self` from outer item //~| NOTE refer to the type directly here instead } } diff --git a/tests/ui/resolve/use-self-in-inner-fn.stderr b/tests/ui/resolve/use-self-in-inner-fn.stderr index 165e100bf2f5c..9c388df8bc20c 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.stderr +++ b/tests/ui/resolve/use-self-in-inner-fn.stderr @@ -1,4 +1,4 @@ -error[E0401]: can't use generic parameters from outer item +error[E0401]: can't use `Self` from outer item --> $DIR/use-self-in-inner-fn.rs:6:25 | LL | impl A { @@ -7,7 +7,7 @@ LL | impl A { LL | fn peach(this: &Self) { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | refer to the type directly here instead error: aborting due to 1 previous error From 1bcaf29e0b3574597341c70a25bf263c77658ba0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 14 Jan 2024 14:13:04 +0100 Subject: [PATCH 094/676] Correctly suggest `std` or `core` path depending if this is a `no_std` crate --- .../src/default_instead_of_iter_empty.rs | 16 +++++++++++----- clippy_lints/src/mem_replace.rs | 19 ++++++++++++++----- .../iter_on_single_or_empty_collections.rs | 10 +++------- .../src/methods/unnecessary_sort_by.rs | 4 ++-- clippy_lints/src/operators/ptr_eq.rs | 8 ++++---- .../src/transmute/transmute_int_to_char.rs | 7 +++++-- .../src/transmute/transmute_ref_to_ref.rs | 8 +++++--- 7 files changed, 44 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs index 2472e2ee76f93..7287b3fcec9b7 100644 --- a/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/clippy_lints/src/default_instead_of_iter_empty.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::last_path_segment; use clippy_utils::source::snippet_with_context; +use clippy_utils::{is_no_std_crate, last_path_segment}; use rustc_errors::Applicability; use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -42,12 +42,17 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty { && ty.span.ctxt() == ctxt { let mut applicability = Applicability::MachineApplicable; - let sugg = make_sugg(cx, ty_path, ctxt, &mut applicability); + let path = if is_no_std_crate(cx) { + "core::iter::empty" + } else { + "std::iter::empty" + }; + let sugg = make_sugg(cx, ty_path, ctxt, &mut applicability, path); span_lint_and_sugg( cx, DEFAULT_INSTEAD_OF_ITER_EMPTY, expr.span, - "`std::iter::empty()` is the more idiomatic way", + &format!("`{path}()` is the more idiomatic way"), "try", sugg, applicability, @@ -61,6 +66,7 @@ fn make_sugg( ty_path: &rustc_hir::QPath<'_>, ctxt: SyntaxContext, applicability: &mut Applicability, + path: &str, ) -> String { if let Some(last) = last_path_segment(ty_path).args && let Some(iter_ty) = last.args.iter().find_map(|arg| match arg { @@ -69,10 +75,10 @@ fn make_sugg( }) { format!( - "std::iter::empty::<{}>()", + "{path}::<{}>()", snippet_with_context(cx, iter_ty.span, ctxt, "..", applicability).0 ) } else { - "std::iter::empty()".to_owned() + format!("{path}()") } } diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index c22f76484d03d..919a959073a7f 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lin use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_non_aggregate_primitive_type; -use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators}; +use clippy_utils::{is_default_equivalent, is_no_std_crate, is_res_lang_ctor, path_res, peel_ref_operators}; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; use rustc_hir::{Expr, ExprKind}; @@ -123,6 +123,10 @@ fn check_replace_option_with_none(cx: &LateContext<'_>, dest: &Expr<'_>, expr_sp ); } +fn get_top_crate(cx: &LateContext<'_>) -> &'static str { + if is_no_std_crate(cx) { "core" } else { "std" } +} + fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(src.hir_id) // check if replacement is mem::MaybeUninit::uninit().assume_init() @@ -136,7 +140,8 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' "replacing with `mem::MaybeUninit::uninit().assume_init()`", "consider using", format!( - "std::ptr::read({})", + "{}::ptr::read({})", + get_top_crate(cx), snippet_with_applicability(cx, dest.span, "", &mut applicability) ), applicability, @@ -157,7 +162,8 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' "replacing with `mem::uninitialized()`", "consider using", format!( - "std::ptr::read({})", + "{}::ptr::read({})", + get_top_crate(cx), snippet_with_applicability(cx, dest.span, "", &mut applicability) ), applicability, @@ -184,14 +190,17 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr< return; } if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) { + let top_crate = get_top_crate(cx); span_lint_and_then( cx, MEM_REPLACE_WITH_DEFAULT, expr_span, - "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`", + &format!( + "replacing a value of type `T` with `T::default()` is better expressed using `{top_crate}::mem::take`" + ), |diag| { if !expr_span.from_expansion() { - let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, "")); + let suggestion = format!("{top_crate}::mem::take({})", snippet(cx, dest.span, "")); diag.span_suggestion( expr_span, diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index 70abe4891d985..e1ed272231a38 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -58,10 +58,10 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re return; } + let top_crate = if is_no_std_crate(cx) { "core" } else { "std" }; if let Some(i) = item { let sugg = format!( - "{}::iter::once({}{})", - if is_no_std_crate(cx) { "core" } else { "std" }, + "{top_crate}::iter::once({}{})", iter_type.ref_prefix(), snippet(cx, i.span, "...") ); @@ -81,11 +81,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re expr.span, &format!("`{method_name}` call on an empty collection"), "try", - if is_no_std_crate(cx) { - "core::iter::empty()".to_string() - } else { - "std::iter::empty()".to_string() - }, + format!("{top_crate}::iter::empty()"), Applicability::MaybeIncorrect, ); } diff --git a/clippy_lints/src/methods/unnecessary_sort_by.rs b/clippy_lints/src/methods/unnecessary_sort_by.rs index 4949ccd770e28..a92fe9e55a469 100644 --- a/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -204,7 +204,7 @@ pub(super) fn check<'tcx>( cx, UNNECESSARY_SORT_BY, expr.span, - "use Vec::sort_by_key here instead", + "consider using `sort_by_key`", "try", format!( "{}.sort{}_by_key(|{}| {})", @@ -227,7 +227,7 @@ pub(super) fn check<'tcx>( cx, UNNECESSARY_SORT_BY, expr.span, - "use Vec::sort here instead", + "consider using `sort`", "try", format!( "{}.sort{}()", diff --git a/clippy_lints/src/operators/ptr_eq.rs b/clippy_lints/src/operators/ptr_eq.rs index 9db2e24630aac..31b51193fb159 100644 --- a/clippy_lints/src/operators/ptr_eq.rs +++ b/clippy_lints/src/operators/ptr_eq.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_no_std_crate; use clippy_utils::source::snippet_opt; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -6,8 +7,6 @@ use rustc_lint::LateContext; use super::PTR_EQ; -static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers"; - pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, @@ -26,13 +25,14 @@ pub(super) fn check<'tcx>( && let Some(left_snip) = snippet_opt(cx, left_var.span) && let Some(right_snip) = snippet_opt(cx, right_var.span) { + let top_crate = if is_no_std_crate(cx) { "core" } else { "std" }; span_lint_and_sugg( cx, PTR_EQ, expr.span, - LINT_MSG, + &format!("use `{top_crate}::ptr::eq` when comparing raw pointers"), "try", - format!("std::ptr::eq({left_snip}, {right_snip})"), + format!("{top_crate}::ptr::eq({left_snip}, {right_snip})"), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/transmute/transmute_int_to_char.rs b/clippy_lints/src/transmute/transmute_int_to_char.rs index 7d31c375f8cf2..71e8a26a566d3 100644 --- a/clippy_lints/src/transmute/transmute_int_to_char.rs +++ b/clippy_lints/src/transmute/transmute_int_to_char.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_INT_TO_CHAR; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::sugg; +use clippy_utils::{is_no_std_crate, sugg}; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::Expr; @@ -34,7 +34,10 @@ pub(super) fn check<'tcx>( diag.span_suggestion( e.span, "consider using", - format!("std::char::from_u32({arg}).unwrap()"), + format!( + "{}::char::from_u32({arg}).unwrap()", + if is_no_std_crate(cx) { "core" } else { "std" } + ), Applicability::Unspecified, ); }, diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 98e9ea2d7751f..c923b4b6dd4a9 100644 --- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -1,7 +1,7 @@ use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet; -use clippy_utils::sugg; +use clippy_utils::{is_no_std_crate, sugg}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; @@ -29,6 +29,8 @@ pub(super) fn check<'tcx>( let snippet = snippet(cx, arg.span, ".."); + let top_crate = if is_no_std_crate(cx) { "core" } else { "std" }; + span_lint_and_sugg( cx, TRANSMUTE_BYTES_TO_STR, @@ -36,9 +38,9 @@ pub(super) fn check<'tcx>( &format!("transmute from a `{from_ty}` to a `{to_ty}`"), "consider using", if const_context { - format!("std::str::from_utf8_unchecked{postfix}({snippet})") + format!("{top_crate}::str::from_utf8_unchecked{postfix}({snippet})") } else { - format!("std::str::from_utf8{postfix}({snippet}).unwrap()") + format!("{top_crate}::str::from_utf8{postfix}({snippet}).unwrap()") }, Applicability::MaybeIncorrect, ); From 40a45a463f3093df0d2bc1a9bd6457fcf4f26b83 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 14 Jan 2024 14:13:26 +0100 Subject: [PATCH 095/676] Update and add ui tests for core/std suggestions --- ...default_instead_of_iter_empty_no_std.fixed | 28 +++++++ .../default_instead_of_iter_empty_no_std.rs | 28 +++++++ ...efault_instead_of_iter_empty_no_std.stderr | 17 ++++ tests/ui/mem_replace_no_std.fixed | 82 +++++++++++++++++++ tests/ui/mem_replace_no_std.rs | 82 +++++++++++++++++++ tests/ui/mem_replace_no_std.stderr | 50 +++++++++++ tests/ui/ptr_eq_no_std.fixed | 49 +++++++++++ tests/ui/ptr_eq_no_std.rs | 49 +++++++++++ tests/ui/ptr_eq_no_std.stderr | 17 ++++ tests/ui/transmute.rs | 13 --- tests/ui/transmute.stderr | 61 ++++++-------- tests/ui/transmute_int_to_char.fixed | 15 ++++ tests/ui/transmute_int_to_char.rs | 15 ++++ tests/ui/transmute_int_to_char.stderr | 17 ++++ tests/ui/transmute_int_to_char_no_std.fixed | 27 ++++++ tests/ui/transmute_int_to_char_no_std.rs | 27 ++++++ tests/ui/transmute_int_to_char_no_std.stderr | 17 ++++ tests/ui/transmute_ref_to_ref.rs | 2 +- tests/ui/transmute_ref_to_ref.stderr | 4 +- tests/ui/transmute_ref_to_ref_no_std.rs | 30 +++++++ tests/ui/transmute_ref_to_ref_no_std.stderr | 26 ++++++ tests/ui/unnecessary_sort_by.stderr | 24 +++--- 22 files changed, 614 insertions(+), 66 deletions(-) create mode 100644 tests/ui/default_instead_of_iter_empty_no_std.fixed create mode 100644 tests/ui/default_instead_of_iter_empty_no_std.rs create mode 100644 tests/ui/default_instead_of_iter_empty_no_std.stderr create mode 100644 tests/ui/mem_replace_no_std.fixed create mode 100644 tests/ui/mem_replace_no_std.rs create mode 100644 tests/ui/mem_replace_no_std.stderr create mode 100644 tests/ui/ptr_eq_no_std.fixed create mode 100644 tests/ui/ptr_eq_no_std.rs create mode 100644 tests/ui/ptr_eq_no_std.stderr create mode 100644 tests/ui/transmute_int_to_char.fixed create mode 100644 tests/ui/transmute_int_to_char.rs create mode 100644 tests/ui/transmute_int_to_char.stderr create mode 100644 tests/ui/transmute_int_to_char_no_std.fixed create mode 100644 tests/ui/transmute_int_to_char_no_std.rs create mode 100644 tests/ui/transmute_int_to_char_no_std.stderr create mode 100644 tests/ui/transmute_ref_to_ref_no_std.rs create mode 100644 tests/ui/transmute_ref_to_ref_no_std.stderr diff --git a/tests/ui/default_instead_of_iter_empty_no_std.fixed b/tests/ui/default_instead_of_iter_empty_no_std.fixed new file mode 100644 index 0000000000000..7300bd9bd2abd --- /dev/null +++ b/tests/ui/default_instead_of_iter_empty_no_std.fixed @@ -0,0 +1,28 @@ +#![warn(clippy::default_instead_of_iter_empty)] +#![allow(dead_code)] +#![feature(lang_items)] +#![no_std] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +#[derive(Default)] +struct Iter { + iter: core::iter::Empty, +} + +fn main() { + // Do lint. + let _ = core::iter::empty::(); + let _foo: core::iter::Empty = core::iter::empty(); + + // Do not lint. + let _ = Iter::default(); +} diff --git a/tests/ui/default_instead_of_iter_empty_no_std.rs b/tests/ui/default_instead_of_iter_empty_no_std.rs new file mode 100644 index 0000000000000..0bc5c7169d129 --- /dev/null +++ b/tests/ui/default_instead_of_iter_empty_no_std.rs @@ -0,0 +1,28 @@ +#![warn(clippy::default_instead_of_iter_empty)] +#![allow(dead_code)] +#![feature(lang_items)] +#![no_std] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +#[derive(Default)] +struct Iter { + iter: core::iter::Empty, +} + +fn main() { + // Do lint. + let _ = core::iter::Empty::::default(); + let _foo: core::iter::Empty = core::iter::Empty::default(); + + // Do not lint. + let _ = Iter::default(); +} diff --git a/tests/ui/default_instead_of_iter_empty_no_std.stderr b/tests/ui/default_instead_of_iter_empty_no_std.stderr new file mode 100644 index 0000000000000..747a31ecbf366 --- /dev/null +++ b/tests/ui/default_instead_of_iter_empty_no_std.stderr @@ -0,0 +1,17 @@ +error: `core::iter::empty()` is the more idiomatic way + --> $DIR/default_instead_of_iter_empty_no_std.rs:23:13 + | +LL | let _ = core::iter::Empty::::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::iter::empty::()` + | + = note: `-D clippy::default-instead-of-iter-empty` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::default_instead_of_iter_empty)]` + +error: `core::iter::empty()` is the more idiomatic way + --> $DIR/default_instead_of_iter_empty_no_std.rs:24:42 + | +LL | let _foo: core::iter::Empty = core::iter::Empty::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::iter::empty()` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/mem_replace_no_std.fixed b/tests/ui/mem_replace_no_std.fixed new file mode 100644 index 0000000000000..c970f2ba2814b --- /dev/null +++ b/tests/ui/mem_replace_no_std.fixed @@ -0,0 +1,82 @@ +#![allow(unused)] +#![warn( + clippy::all, + clippy::style, + clippy::mem_replace_option_with_none, + clippy::mem_replace_with_default +)] +#![feature(lang_items)] +#![no_std] + +use core::mem; +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +fn replace_option_with_none() { + let mut an_option = Some(1); + let _ = an_option.take(); + let an_option = &mut Some(1); + let _ = an_option.take(); +} + +fn replace_with_default() { + let mut refstr = "hello"; + let _ = core::mem::take(&mut refstr); + + let mut slice: &[i32] = &[1, 2, 3]; + let _ = core::mem::take(&mut slice); +} + +// lint is disabled for primitives because in this case `take` +// has no clear benefit over `replace` and sometimes is harder to read +fn dont_lint_primitive() { + let mut pbool = true; + let _ = mem::replace(&mut pbool, false); + + let mut pint = 5; + let _ = mem::replace(&mut pint, 0); +} + +fn main() { + replace_option_with_none(); + replace_with_default(); + dont_lint_primitive(); +} + +fn issue9824() { + struct Foo<'a>(Option<&'a str>); + impl<'a> core::ops::Deref for Foo<'a> { + type Target = Option<&'a str>; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl<'a> core::ops::DerefMut for Foo<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + struct Bar { + opt: Option, + val: u8, + } + + let mut f = Foo(Some("foo")); + let mut b = Bar { opt: Some(1), val: 12 }; + + // replace option with none + let _ = f.0.take(); + let _ = (*f).take(); + let _ = b.opt.take(); + // replace with default + let _ = mem::replace(&mut b.val, u8::default()); +} diff --git a/tests/ui/mem_replace_no_std.rs b/tests/ui/mem_replace_no_std.rs new file mode 100644 index 0000000000000..673d5c7b4f45a --- /dev/null +++ b/tests/ui/mem_replace_no_std.rs @@ -0,0 +1,82 @@ +#![allow(unused)] +#![warn( + clippy::all, + clippy::style, + clippy::mem_replace_option_with_none, + clippy::mem_replace_with_default +)] +#![feature(lang_items)] +#![no_std] + +use core::mem; +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +fn replace_option_with_none() { + let mut an_option = Some(1); + let _ = mem::replace(&mut an_option, None); + let an_option = &mut Some(1); + let _ = mem::replace(an_option, None); +} + +fn replace_with_default() { + let mut refstr = "hello"; + let _ = mem::replace(&mut refstr, ""); + + let mut slice: &[i32] = &[1, 2, 3]; + let _ = mem::replace(&mut slice, &[]); +} + +// lint is disabled for primitives because in this case `take` +// has no clear benefit over `replace` and sometimes is harder to read +fn dont_lint_primitive() { + let mut pbool = true; + let _ = mem::replace(&mut pbool, false); + + let mut pint = 5; + let _ = mem::replace(&mut pint, 0); +} + +fn main() { + replace_option_with_none(); + replace_with_default(); + dont_lint_primitive(); +} + +fn issue9824() { + struct Foo<'a>(Option<&'a str>); + impl<'a> core::ops::Deref for Foo<'a> { + type Target = Option<&'a str>; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl<'a> core::ops::DerefMut for Foo<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + struct Bar { + opt: Option, + val: u8, + } + + let mut f = Foo(Some("foo")); + let mut b = Bar { opt: Some(1), val: 12 }; + + // replace option with none + let _ = mem::replace(&mut f.0, None); + let _ = mem::replace(&mut *f, None); + let _ = mem::replace(&mut b.opt, None); + // replace with default + let _ = mem::replace(&mut b.val, u8::default()); +} diff --git a/tests/ui/mem_replace_no_std.stderr b/tests/ui/mem_replace_no_std.stderr new file mode 100644 index 0000000000000..744fb5a15876e --- /dev/null +++ b/tests/ui/mem_replace_no_std.stderr @@ -0,0 +1,50 @@ +error: replacing an `Option` with `None` + --> $DIR/mem_replace_no_std.rs:24:13 + | +LL | let _ = mem::replace(&mut an_option, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` + | + = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::mem_replace_option_with_none)]` + +error: replacing an `Option` with `None` + --> $DIR/mem_replace_no_std.rs:26:13 + | +LL | let _ = mem::replace(an_option, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` + +error: replacing a value of type `T` with `T::default()` is better expressed using `core::mem::take` + --> $DIR/mem_replace_no_std.rs:31:13 + | +LL | let _ = mem::replace(&mut refstr, ""); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut refstr)` + | + = note: `-D clippy::mem-replace-with-default` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::mem_replace_with_default)]` + +error: replacing a value of type `T` with `T::default()` is better expressed using `core::mem::take` + --> $DIR/mem_replace_no_std.rs:34:13 + | +LL | let _ = mem::replace(&mut slice, &[]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut slice)` + +error: replacing an `Option` with `None` + --> $DIR/mem_replace_no_std.rs:77:13 + | +LL | let _ = mem::replace(&mut f.0, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()` + +error: replacing an `Option` with `None` + --> $DIR/mem_replace_no_std.rs:78:13 + | +LL | let _ = mem::replace(&mut *f, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()` + +error: replacing an `Option` with `None` + --> $DIR/mem_replace_no_std.rs:79:13 + | +LL | let _ = mem::replace(&mut b.opt, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/ptr_eq_no_std.fixed b/tests/ui/ptr_eq_no_std.fixed new file mode 100644 index 0000000000000..97c8c394c03d4 --- /dev/null +++ b/tests/ui/ptr_eq_no_std.fixed @@ -0,0 +1,49 @@ +#![warn(clippy::ptr_eq)] +#![no_std] +#![feature(lang_items)] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +macro_rules! mac { + ($a:expr, $b:expr) => { + $a as *const _ as usize == $b as *const _ as usize + }; +} + +macro_rules! another_mac { + ($a:expr, $b:expr) => { + $a as *const _ == $b as *const _ + }; +} + +fn main() { + let a = &[1, 2, 3]; + let b = &[1, 2, 3]; + + let _ = core::ptr::eq(a, b); + let _ = core::ptr::eq(a, b); + let _ = a.as_ptr() == b as *const _; + let _ = a.as_ptr() == b.as_ptr(); + + // Do not lint + + let _ = mac!(a, b); + let _ = another_mac!(a, b); + + let a = &mut [1, 2, 3]; + let b = &mut [1, 2, 3]; + + let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + let _ = a.as_mut_ptr() == b.as_mut_ptr(); + + let _ = a == b; + let _ = core::ptr::eq(a, b); +} diff --git a/tests/ui/ptr_eq_no_std.rs b/tests/ui/ptr_eq_no_std.rs new file mode 100644 index 0000000000000..a7ba9b4d81746 --- /dev/null +++ b/tests/ui/ptr_eq_no_std.rs @@ -0,0 +1,49 @@ +#![warn(clippy::ptr_eq)] +#![no_std] +#![feature(lang_items)] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +macro_rules! mac { + ($a:expr, $b:expr) => { + $a as *const _ as usize == $b as *const _ as usize + }; +} + +macro_rules! another_mac { + ($a:expr, $b:expr) => { + $a as *const _ == $b as *const _ + }; +} + +fn main() { + let a = &[1, 2, 3]; + let b = &[1, 2, 3]; + + let _ = a as *const _ as usize == b as *const _ as usize; + let _ = a as *const _ == b as *const _; + let _ = a.as_ptr() == b as *const _; + let _ = a.as_ptr() == b.as_ptr(); + + // Do not lint + + let _ = mac!(a, b); + let _ = another_mac!(a, b); + + let a = &mut [1, 2, 3]; + let b = &mut [1, 2, 3]; + + let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + let _ = a.as_mut_ptr() == b.as_mut_ptr(); + + let _ = a == b; + let _ = core::ptr::eq(a, b); +} diff --git a/tests/ui/ptr_eq_no_std.stderr b/tests/ui/ptr_eq_no_std.stderr new file mode 100644 index 0000000000000..3e289f5be613e --- /dev/null +++ b/tests/ui/ptr_eq_no_std.stderr @@ -0,0 +1,17 @@ +error: use `core::ptr::eq` when comparing raw pointers + --> $DIR/ptr_eq_no_std.rs:31:13 + | +LL | let _ = a as *const _ as usize == b as *const _ as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)` + | + = note: `-D clippy::ptr-eq` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]` + +error: use `core::ptr::eq` when comparing raw pointers + --> $DIR/ptr_eq_no_std.rs:32:13 + | +LL | let _ = a as *const _ == b as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 32f6027e99111..1796ccaf28e1a 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -102,19 +102,6 @@ fn crosspointer() { } } -#[warn(clippy::transmute_int_to_char)] -fn int_to_char() { - let _: char = unsafe { std::mem::transmute(0_u32) }; - //~^ ERROR: transmute from a `u32` to a `char` - //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` - let _: char = unsafe { std::mem::transmute(0_i32) }; - //~^ ERROR: transmute from a `i32` to a `char` - - // These shouldn't warn - const _: char = unsafe { std::mem::transmute(0_u32) }; - const _: char = unsafe { std::mem::transmute(0_i32) }; -} - #[warn(clippy::transmute_int_to_bool)] fn int_to_bool() { let _: bool = unsafe { std::mem::transmute(0_u8) }; diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index cdc733b54a9b2..df32d478cbf40 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -88,23 +88,8 @@ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) LL | let _: *mut Usize = core::intrinsics::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: transmute from a `u32` to a `char` - --> $DIR/transmute.rs:107:28 - | -LL | let _: char = unsafe { std::mem::transmute(0_u32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` - | - = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]` - -error: transmute from a `i32` to a `char` - --> $DIR/transmute.rs:110:28 - | -LL | let _: char = unsafe { std::mem::transmute(0_i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` - error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:120:28 + --> $DIR/transmute.rs:107:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -113,7 +98,7 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:128:31 + --> $DIR/transmute.rs:115:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` @@ -122,25 +107,25 @@ LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_float)]` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:131:31 + --> $DIR/transmute.rs:118:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` error: transmute from a `u64` to a `f64` - --> $DIR/transmute.rs:133:31 + --> $DIR/transmute.rs:120:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)` error: transmute from a `i64` to a `f64` - --> $DIR/transmute.rs:135:31 + --> $DIR/transmute.rs:122:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` error: transmute from a `u8` to a `[u8; 1]` - --> $DIR/transmute.rs:156:30 + --> $DIR/transmute.rs:143:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` @@ -149,85 +134,85 @@ LL | let _: [u8; 1] = std::mem::transmute(0u8); = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]` error: transmute from a `u32` to a `[u8; 4]` - --> $DIR/transmute.rs:159:30 + --> $DIR/transmute.rs:146:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> $DIR/transmute.rs:161:31 + --> $DIR/transmute.rs:148:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> $DIR/transmute.rs:163:30 + --> $DIR/transmute.rs:150:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> $DIR/transmute.rs:165:30 + --> $DIR/transmute.rs:152:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> $DIR/transmute.rs:167:31 + --> $DIR/transmute.rs:154:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `f32` to a `[u8; 4]` - --> $DIR/transmute.rs:169:30 + --> $DIR/transmute.rs:156:30 | LL | let _: [u8; 4] = std::mem::transmute(0.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` error: transmute from a `f64` to a `[u8; 8]` - --> $DIR/transmute.rs:171:30 + --> $DIR/transmute.rs:158:30 | LL | let _: [u8; 8] = std::mem::transmute(0.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` error: transmute from a `u8` to a `[u8; 1]` - --> $DIR/transmute.rs:177:30 + --> $DIR/transmute.rs:164:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` error: transmute from a `u32` to a `[u8; 4]` - --> $DIR/transmute.rs:179:30 + --> $DIR/transmute.rs:166:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> $DIR/transmute.rs:181:31 + --> $DIR/transmute.rs:168:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> $DIR/transmute.rs:183:30 + --> $DIR/transmute.rs:170:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> $DIR/transmute.rs:185:30 + --> $DIR/transmute.rs:172:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> $DIR/transmute.rs:187:31 + --> $DIR/transmute.rs:174:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:198:28 + --> $DIR/transmute.rs:185:28 | LL | let _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()` @@ -236,16 +221,16 @@ LL | let _: &str = unsafe { std::mem::transmute(B) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:201:32 + --> $DIR/transmute.rs:188:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:203:30 + --> $DIR/transmute.rs:190:30 | LL | const _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)` -error: aborting due to 38 previous errors +error: aborting due to 36 previous errors diff --git a/tests/ui/transmute_int_to_char.fixed b/tests/ui/transmute_int_to_char.fixed new file mode 100644 index 0000000000000..1708011817541 --- /dev/null +++ b/tests/ui/transmute_int_to_char.fixed @@ -0,0 +1,15 @@ +#![warn(clippy::transmute_int_to_char)] + +fn int_to_char() { + let _: char = unsafe { std::char::from_u32(0_u32).unwrap() }; + //~^ ERROR: transmute from a `u32` to a `char` + //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` + let _: char = unsafe { std::char::from_u32(0_i32 as u32).unwrap() }; + //~^ ERROR: transmute from a `i32` to a `char` + + // These shouldn't warn + const _: char = unsafe { std::mem::transmute(0_u32) }; + const _: char = unsafe { std::mem::transmute(0_i32) }; +} + +fn main() {} diff --git a/tests/ui/transmute_int_to_char.rs b/tests/ui/transmute_int_to_char.rs new file mode 100644 index 0000000000000..5846a97e88abf --- /dev/null +++ b/tests/ui/transmute_int_to_char.rs @@ -0,0 +1,15 @@ +#![warn(clippy::transmute_int_to_char)] + +fn int_to_char() { + let _: char = unsafe { std::mem::transmute(0_u32) }; + //~^ ERROR: transmute from a `u32` to a `char` + //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` + let _: char = unsafe { std::mem::transmute(0_i32) }; + //~^ ERROR: transmute from a `i32` to a `char` + + // These shouldn't warn + const _: char = unsafe { std::mem::transmute(0_u32) }; + const _: char = unsafe { std::mem::transmute(0_i32) }; +} + +fn main() {} diff --git a/tests/ui/transmute_int_to_char.stderr b/tests/ui/transmute_int_to_char.stderr new file mode 100644 index 0000000000000..2297f5b4f8bf2 --- /dev/null +++ b/tests/ui/transmute_int_to_char.stderr @@ -0,0 +1,17 @@ +error: transmute from a `u32` to a `char` + --> $DIR/transmute_int_to_char.rs:4:28 + | +LL | let _: char = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()` + | + = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]` + +error: transmute from a `i32` to a `char` + --> $DIR/transmute_int_to_char.rs:7:28 + | +LL | let _: char = unsafe { std::mem::transmute(0_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/transmute_int_to_char_no_std.fixed b/tests/ui/transmute_int_to_char_no_std.fixed new file mode 100644 index 0000000000000..9ae4e11fb56e7 --- /dev/null +++ b/tests/ui/transmute_int_to_char_no_std.fixed @@ -0,0 +1,27 @@ +#![no_std] +#![feature(lang_items)] +#![warn(clippy::transmute_int_to_char)] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +fn int_to_char() { + let _: char = unsafe { core::char::from_u32(0_u32).unwrap() }; + //~^ ERROR: transmute from a `u32` to a `char` + //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` + let _: char = unsafe { core::char::from_u32(0_i32 as u32).unwrap() }; + //~^ ERROR: transmute from a `i32` to a `char` + + // These shouldn't warn + const _: char = unsafe { core::mem::transmute(0_u32) }; + const _: char = unsafe { core::mem::transmute(0_i32) }; +} + +fn main() {} diff --git a/tests/ui/transmute_int_to_char_no_std.rs b/tests/ui/transmute_int_to_char_no_std.rs new file mode 100644 index 0000000000000..9a2afd5bd2fd6 --- /dev/null +++ b/tests/ui/transmute_int_to_char_no_std.rs @@ -0,0 +1,27 @@ +#![no_std] +#![feature(lang_items)] +#![warn(clippy::transmute_int_to_char)] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +fn int_to_char() { + let _: char = unsafe { core::mem::transmute(0_u32) }; + //~^ ERROR: transmute from a `u32` to a `char` + //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` + let _: char = unsafe { core::mem::transmute(0_i32) }; + //~^ ERROR: transmute from a `i32` to a `char` + + // These shouldn't warn + const _: char = unsafe { core::mem::transmute(0_u32) }; + const _: char = unsafe { core::mem::transmute(0_i32) }; +} + +fn main() {} diff --git a/tests/ui/transmute_int_to_char_no_std.stderr b/tests/ui/transmute_int_to_char_no_std.stderr new file mode 100644 index 0000000000000..aace6968696da --- /dev/null +++ b/tests/ui/transmute_int_to_char_no_std.stderr @@ -0,0 +1,17 @@ +error: transmute from a `u32` to a `char` + --> $DIR/transmute_int_to_char_no_std.rs:16:28 + | +LL | let _: char = unsafe { core::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::char::from_u32(0_u32).unwrap()` + | + = note: `-D clippy::transmute-int-to-char` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]` + +error: transmute from a `i32` to a `char` + --> $DIR/transmute_int_to_char_no_std.rs:19:28 + | +LL | let _: char = unsafe { core::mem::transmute(0_i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::char::from_u32(0_i32 as u32).unwrap()` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/transmute_ref_to_ref.rs b/tests/ui/transmute_ref_to_ref.rs index e7f35c5743684..bdc7b9f647877 100644 --- a/tests/ui/transmute_ref_to_ref.rs +++ b/tests/ui/transmute_ref_to_ref.rs @@ -12,7 +12,7 @@ fn main() { let b: &[u8] = unsafe { std::mem::transmute(a) }; //~^ ERROR: transmute from a reference to a reference let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; - let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; + let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) }; //~^ ERROR: transmute from a reference to a reference } } diff --git a/tests/ui/transmute_ref_to_ref.stderr b/tests/ui/transmute_ref_to_ref.stderr index cc6b156b18885..4238bc637ad04 100644 --- a/tests/ui/transmute_ref_to_ref.stderr +++ b/tests/ui/transmute_ref_to_ref.stderr @@ -19,8 +19,8 @@ LL | let b: &[u8] = unsafe { std::mem::transmute(a) }; error: transmute from a reference to a reference --> $DIR/transmute_ref_to_ref.rs:15:42 | -LL | let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` +LL | let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` error: aborting due to 3 previous errors diff --git a/tests/ui/transmute_ref_to_ref_no_std.rs b/tests/ui/transmute_ref_to_ref_no_std.rs new file mode 100644 index 0000000000000..b67386f858852 --- /dev/null +++ b/tests/ui/transmute_ref_to_ref_no_std.rs @@ -0,0 +1,30 @@ +//@no-rustfix + +#![deny(clippy::transmute_ptr_to_ptr)] +#![allow(dead_code)] +#![feature(lang_items)] +#![no_std] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +fn main() { + unsafe { + let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF]; + let bools: &[bool] = unsafe { core::mem::transmute(single_u64) }; + //~^ ERROR: transmute from a reference to a reference + let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321]; + let b: &[u8] = unsafe { core::mem::transmute(a) }; + //~^ ERROR: transmute from a reference to a reference + let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; + let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; + //~^ ERROR: transmute from a reference to a reference + } +} diff --git a/tests/ui/transmute_ref_to_ref_no_std.stderr b/tests/ui/transmute_ref_to_ref_no_std.stderr new file mode 100644 index 0000000000000..ca7966ffa9e88 --- /dev/null +++ b/tests/ui/transmute_ref_to_ref_no_std.stderr @@ -0,0 +1,26 @@ +error: transmute from a reference to a reference + --> $DIR/transmute_ref_to_ref_no_std.rs:21:39 + | +LL | let bools: &[bool] = unsafe { core::mem::transmute(single_u64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(single_u64 as *const [u64] as *const [bool])` + | +note: the lint level is defined here + --> $DIR/transmute_ref_to_ref_no_std.rs:3:9 + | +LL | #![deny(clippy::transmute_ptr_to_ptr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmute from a reference to a reference + --> $DIR/transmute_ref_to_ref_no_std.rs:24:33 + | +LL | let b: &[u8] = unsafe { core::mem::transmute(a) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])` + +error: transmute from a reference to a reference + --> $DIR/transmute_ref_to_ref_no_std.rs:27:42 + | +LL | let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index 9d54c8d50e31f..f4409113a45fa 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -1,4 +1,4 @@ -error: use Vec::sort here instead +error: consider using `sort` --> $DIR/unnecessary_sort_by.rs:12:5 | LL | vec.sort_by(|a, b| a.cmp(b)); @@ -7,67 +7,67 @@ LL | vec.sort_by(|a, b| a.cmp(b)); = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` -error: use Vec::sort here instead +error: consider using `sort` --> $DIR/unnecessary_sort_by.rs:13:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:14:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:15:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| id(-a))` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:18:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:19:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b)))` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:29:5 | LL | vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:30:5 | LL | vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| (***a).abs())` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:89:9 | LL | args.sort_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:90:9 | LL | args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|a| a.name())` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:92:9 | LL | args.sort_by(|a, b| b.name().cmp(&a.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))` -error: use Vec::sort_by_key here instead +error: consider using `sort_by_key` --> $DIR/unnecessary_sort_by.rs:93:9 | LL | args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); From 5d06fbb46d2434c50d3c50695e4a0f0bb187fdb5 Mon Sep 17 00:00:00 2001 From: Kristof Mattei <864376+Kristof-Mattei@users.noreply.github.com> Date: Sun, 14 Jan 2024 09:25:31 -0700 Subject: [PATCH 096/676] fix: don't allocate new string when not needed --- clippy_lints/src/cargo/multiple_crate_versions.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs index a28934266cbc1..8e86c0017e1d5 100644 --- a/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -16,7 +16,12 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { if let Some(resolve) = &metadata.resolve && let Some(local_id) = packages.iter().find_map(|p| { - if p.name.replace('-', "_") == local_name.as_str() { + if p.name + .chars() + .into_iter() + .map(|c| if c == '-' { '_' } else { c }) + .eq(local_name.as_str().chars()) + { Some(&p.id) } else { None From b1c52d502d6c0441c944225287281c70282c1c9b Mon Sep 17 00:00:00 2001 From: Kristof Mattei <864376+Kristof-Mattei@users.noreply.github.com> Date: Sun, 14 Jan 2024 09:32:36 -0700 Subject: [PATCH 097/676] chore: add comments to explain reasoning --- clippy_lints/src/cargo/multiple_crate_versions.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs index 8e86c0017e1d5..c487ffb1c8224 100644 --- a/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -16,6 +16,9 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { if let Some(resolve) = &metadata.resolve && let Some(local_id) = packages.iter().find_map(|p| { + // p.name contains the original crate names with dashes intact + // local_name contains the crate name as a namespace, with the dashes converted to underscores + // the code below temporarily rectifies this discrepancy if p.name .chars() .into_iter() From ea585ef321b6ba63635984772fe576e6a4e461fc Mon Sep 17 00:00:00 2001 From: Kristof Mattei <864376+Kristof-Mattei@users.noreply.github.com> Date: Sun, 14 Jan 2024 09:40:14 -0700 Subject: [PATCH 098/676] chore: remove unneeded into_iter --- clippy_lints/src/cargo/multiple_crate_versions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs index c487ffb1c8224..6b4af6753c3e8 100644 --- a/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -21,7 +21,6 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { // the code below temporarily rectifies this discrepancy if p.name .chars() - .into_iter() .map(|c| if c == '-' { '_' } else { c }) .eq(local_name.as_str().chars()) { From e8ec99811b80372012d3ece0e0f31f5722785eec Mon Sep 17 00:00:00 2001 From: Kristof Mattei <864376+Kristof-Mattei@users.noreply.github.com> Date: Sun, 14 Jan 2024 14:00:13 -0700 Subject: [PATCH 099/676] fix: crates are limited to ASCII values --- clippy_lints/src/cargo/multiple_crate_versions.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs index 6b4af6753c3e8..57b7b7497fe24 100644 --- a/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -20,9 +20,10 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { // local_name contains the crate name as a namespace, with the dashes converted to underscores // the code below temporarily rectifies this discrepancy if p.name - .chars() - .map(|c| if c == '-' { '_' } else { c }) - .eq(local_name.as_str().chars()) + .as_bytes() + .iter() + .map(|b| if b == &b'-' { &b'_' } else { b }) + .eq(local_name.as_str().as_bytes()) { Some(&p.id) } else { From 5747eceef859c6e1ac74c04723ac9e2b5e039e1f Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 14 Jan 2024 22:35:00 -0800 Subject: [PATCH 100/676] 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 33d8e47e98bf45fdc105d1fadb37dd03789ba1b3 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sun, 10 Dec 2023 07:34:48 +0100 Subject: [PATCH 101/676] Try to improve wording and fix dead link in description of arc_with_non_send_sync lint. --- clippy_lints/src/arc_with_non_send_sync.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index 58738d5287883..1102c7fb236b5 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -14,10 +14,10 @@ declare_clippy_lint! { /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`. /// /// ### Why is this bad? - /// `Arc` is an Atomic `Rc` and guarantees that updates to the reference counter are - /// Atomic. This is useful in multithreading scenarios. To send an `Arc` across threads - /// and make use of the atomic ref counter, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E), - /// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc` + /// `Arc` is a thread-safe `Rc` and guarantees that updates to the reference counter + /// use atomic operations. To send an `Arc` across thread boundaries and + /// share ownership between multiple threads, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#thread-safety), + /// so either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc` /// /// ### Example /// ```no_run From a16a85030c6a75bf7cea901118c2f0a67033048d Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Mon, 4 Dec 2023 21:17:47 +0000 Subject: [PATCH 102/676] Add "OpenTelemetry" to default `doc_valid_idents` The OpenTelemetry project's name is all one word (see https://opentelemetry.io), so currently triggers a false positive in the `doc_markdown` lint. The project is increasing rapidly in popularity, so it seems like a worthy contender for inclusion in the default `doc_valid_idents` configuration. I've also moved the existing "OpenDNS" entry earlier in the list, to restore the alphabetical ordering of that "Open*" row. The docs changes were generated using `cargo collect-metadata`. changelog: [`doc_markdown`]: Add `OpenTelemetry` to the default configuration as an allowed identifier --- book/src/lint_configuration.md | 2 +- clippy_config/src/conf.rs | 2 +- tests/ui/doc/doc-fixable.fixed | 2 +- tests/ui/doc/doc-fixable.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 3b62ae0524ab0..16e343401c40d 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -212,7 +212,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 5477d9b83a72c..76e25a814b2b9 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -26,7 +26,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", - "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", + "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index bff46e55722ba..16f7bafd44b78 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -64,7 +64,7 @@ fn test_units() { /// NaN NaNs /// OAuth GraphQL /// OCaml -/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS +/// OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry /// WebGL WebGL2 WebGPU /// TensorFlow /// TrueType diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index 4e162a97dee9b..4058b2bad74f7 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -64,7 +64,7 @@ fn test_units() { /// NaN NaNs /// OAuth GraphQL /// OCaml -/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS +/// OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry /// WebGL WebGL2 WebGPU /// TensorFlow /// TrueType From 6c201db005c546bb16ce19c81d6b68f262b0203a Mon Sep 17 00:00:00 2001 From: atwam Date: Wed, 4 Oct 2023 13:56:18 +0100 Subject: [PATCH 103/676] Add suspicious_open_options lint. Checks for the suspicious use of OpenOptions::create() without an explicit OpenOptions::truncate(). create() alone will either create a new file or open an existing file. If the file already exists, it will be overwritten when written to, but the file will not be truncated by default. If less data is written to the file than it already contains, the remainder of the file will remain unchanged, and the end of the file will contain old data. In most cases, one should either use `create_new` to ensure the file is created from scratch, or ensure `truncate` is called so that the truncation behaviour is explicit. `truncate(true)` will ensure the file is entirely overwritten with new data, whereas `truncate(false)` will explicitely keep the default behavior. ```rust use std::fs::OpenOptions; OpenOptions::new().create(true).truncate(true); ``` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/methods/mod.rs | 32 ++++ clippy_lints/src/methods/open_options.rs | 156 +++++++----------- tests/ui/open_options.rs | 3 + tests/ui/open_options.stderr | 31 +++- .../ui/seek_to_start_instead_of_rewind.fixed | 3 + tests/ui/seek_to_start_instead_of_rewind.rs | 3 + .../ui/seek_to_start_instead_of_rewind.stderr | 2 +- 9 files changed, 131 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d32bbec914a7..db4b4c2aef60c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5606,6 +5606,7 @@ Released 2018-09-13 [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting [`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl +[`suspicious_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_open_options [`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings [`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_splitn [`suspicious_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_to_owned diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 20230106d5366..639edd8da3012 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -439,6 +439,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::STR_SPLIT_AT_NEWLINE_INFO, crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO, crate::methods::SUSPICIOUS_MAP_INFO, + crate::methods::SUSPICIOUS_OPEN_OPTIONS_INFO, crate::methods::SUSPICIOUS_SPLITN_INFO, crate::methods::SUSPICIOUS_TO_OWNED_INFO, crate::methods::TYPE_ID_ON_BOX_INFO, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 89ea3597dc0fd..84fb583595b9c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2827,6 +2827,37 @@ declare_clippy_lint! { "nonsensical combination of options for opening a file" } +declare_clippy_lint! { + /// ### What it does + /// Checks for the suspicious use of OpenOptions::create() + /// without an explicit OpenOptions::truncate(). + /// + /// ### Why is this bad? + /// create() alone will either create a new file or open an + /// existing file. If the file already exists, it will be + /// overwritten when written to, but the file will not be + /// truncated by default. If less data is written to the file + /// than it already contains, the remainder of the file will + /// remain unchanged, and the end of the file will contain old + /// data. + /// In most cases, one should either use `create_new` to ensure + /// the file is created from scratch, or ensure `truncate` is + /// called so that the truncation behaviour is explicit. `truncate(true)` + /// will ensure the file is entirely overwritten with new data, whereas + /// `truncate(false)` will explicitely keep the default behavior. + /// + /// ### Example + /// ```rust + /// use std::fs::OpenOptions; + /// + /// OpenOptions::new().create(true).truncate(true); + /// ``` + #[clippy::version = "1.73.0"] + pub SUSPICIOUS_OPEN_OPTIONS, + suspicious, + "suspicious combination of options for opening a file" +} + declare_clippy_lint! { /// ### What it does ///* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push) @@ -4033,6 +4064,7 @@ impl_lint_pass!(Methods => [ MAP_ERR_IGNORE, MUT_MUTEX_LOCK, NONSENSICAL_OPEN_OPTIONS, + SUSPICIOUS_OPEN_OPTIONS, PATH_BUF_PUSH_OVERWRITE, RANGE_ZIP_WITH_LEN, REPEAT_ONCE, diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index 65c986dcaccea..81508a5cf65a4 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -1,3 +1,5 @@ +use rustc_data_structures::fx::FxHashMap; + use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; @@ -6,7 +8,7 @@ use rustc_lint::LateContext; use rustc_span::source_map::Spanned; use rustc_span::{sym, Span}; -use super::NONSENSICAL_OPEN_OPTIONS; +use super::{NONSENSICAL_OPEN_OPTIONS, SUSPICIOUS_OPEN_OPTIONS}; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) @@ -19,20 +21,32 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx } } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Eq, PartialEq, Clone)] enum Argument { - True, - False, + Set(bool), Unknown, } -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq, Hash, Clone)] enum OpenOption { - Write, + Append, + Create, + CreateNew, Read, Truncate, - Create, - Append, + Write, +} +impl std::fmt::Display for OpenOption { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + OpenOption::Append => write!(f, "append"), + OpenOption::Create => write!(f, "create"), + OpenOption::CreateNew => write!(f, "create_new"), + OpenOption::Read => write!(f, "read"), + OpenOption::Truncate => write!(f, "truncate"), + OpenOption::Write => write!(f, "write"), + } + } } fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) { @@ -48,7 +62,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec .. } = span { - if *lit { Argument::True } else { Argument::False } + Argument::Set(*lit) } else { // The function is called with a literal which is not a boolean literal. // This is theoretically possible, but not very likely. @@ -62,6 +76,9 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec "create" => { options.push((OpenOption::Create, argument_option)); }, + "create_new" => { + options.push((OpenOption::CreateNew, argument_option)); + }, "append" => { options.push((OpenOption::Append, argument_option)); }, @@ -82,97 +99,52 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec } } -fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)], span: Span) { - let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false); - let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) = - (false, false, false, false, false); - // This code is almost duplicated (oh, the irony), but I haven't found a way to - // unify it. +fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument)], span: Span) { + // The args passed to these methods, if they have been called + let mut options = FxHashMap::default(); + for (option, arg) in settings { + if options.insert(option.clone(), arg.clone()).is_some() { + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + &format!("the method `{}` is called more than once", &option), + ); + } + } - for option in options { - match *option { - (OpenOption::Create, arg) => { - if create { - span_lint( - cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method `create` is called more than once", - ); - } else { - create = true; - } - create_arg = create_arg || (arg == Argument::True); - }, - (OpenOption::Append, arg) => { - if append { - span_lint( - cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method `append` is called more than once", - ); - } else { - append = true; - } - append_arg = append_arg || (arg == Argument::True); - }, - (OpenOption::Truncate, arg) => { - if truncate { - span_lint( - cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method `truncate` is called more than once", - ); - } else { - truncate = true; - } - truncate_arg = truncate_arg || (arg == Argument::True); - }, - (OpenOption::Read, arg) => { - if read { - span_lint( - cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method `read` is called more than once", - ); - } else { - read = true; - } - read_arg = read_arg || (arg == Argument::True); - }, - (OpenOption::Write, arg) => { - if write { - span_lint( - cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "the method `write` is called more than once", - ); - } else { - write = true; - } - write_arg = write_arg || (arg == Argument::True); - }, + if let (Some(Argument::Set(true)), Some(Argument::Set(true))) = + (options.get(&OpenOption::Read), options.get(&OpenOption::Truncate)) + { + if options.get(&OpenOption::Write).unwrap_or(&Argument::Set(false)) == &Argument::Set(false) { + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "file opened with `truncate` and `read`", + ); } } - if read && truncate && read_arg && truncate_arg && !(write && write_arg) { - span_lint( - cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "file opened with `truncate` and `read`", - ); + if let (Some(Argument::Set(true)), Some(Argument::Set(true))) = + (options.get(&OpenOption::Append), options.get(&OpenOption::Truncate)) + { + if options.get(&OpenOption::Write).unwrap_or(&Argument::Set(false)) == &Argument::Set(false) { + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "file opened with `append` and `truncate`", + ); + } } - if append && truncate && append_arg && truncate_arg { + + if let (Some(Argument::Set(true)), None) = (options.get(&OpenOption::Create), options.get(&OpenOption::Truncate)) { span_lint( cx, - NONSENSICAL_OPEN_OPTIONS, + SUSPICIOUS_OPEN_OPTIONS, span, - "file opened with `append` and `truncate`", + "file opened with `create`, but `truncate` behavior not defined", ); } } diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index 0cdc5bf2bb592..dd380f4101add 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -2,6 +2,7 @@ use std::fs::OpenOptions; #[allow(unused_must_use)] #[warn(clippy::nonsensical_open_options)] +#[warn(clippy::suspicious_open_options)] fn main() { OpenOptions::new().read(true).truncate(true).open("foo.txt"); //~^ ERROR: file opened with `truncate` and `read` @@ -19,4 +20,6 @@ fn main() { //~^ ERROR: the method `append` is called more than once OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); //~^ ERROR: the method `truncate` is called more than once + OpenOptions::new().create(true).open("foo.txt"); + //~^ ERROR: file opened with `create`, but `truncate` behavior not defined } diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 7ac826f52fa9d..be6be250f22a3 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -1,5 +1,5 @@ error: file opened with `truncate` and `read` - --> $DIR/open_options.rs:6:5 + --> $DIR/open_options.rs:7:5 | LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,40 +8,55 @@ LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); = help: to override `-D warnings` add `#[allow(clippy::nonsensical_open_options)]` error: file opened with `append` and `truncate` - --> $DIR/open_options.rs:9:5 + --> $DIR/open_options.rs:10:5 | LL | OpenOptions::new().append(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method `read` is called more than once - --> $DIR/open_options.rs:12:5 + --> $DIR/open_options.rs:13:5 | LL | OpenOptions::new().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method `create` is called more than once - --> $DIR/open_options.rs:14:5 + --> $DIR/open_options.rs:15:5 | LL | OpenOptions::new().create(true).create(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: file opened with `create`, but `truncate` behavior not defined + --> $DIR/open_options.rs:15:5 + | +LL | OpenOptions::new().create(true).create(false).open("foo.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::suspicious-open-options` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]` + error: the method `write` is called more than once - --> $DIR/open_options.rs:16:5 + --> $DIR/open_options.rs:17:5 | LL | OpenOptions::new().write(true).write(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method `append` is called more than once - --> $DIR/open_options.rs:18:5 + --> $DIR/open_options.rs:19:5 | LL | OpenOptions::new().append(true).append(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method `truncate` is called more than once - --> $DIR/open_options.rs:20:5 + --> $DIR/open_options.rs:21:5 | LL | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: file opened with `create`, but `truncate` behavior not defined + --> $DIR/open_options.rs:23:5 + | +LL | OpenOptions::new().create(true).open("foo.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors diff --git a/tests/ui/seek_to_start_instead_of_rewind.fixed b/tests/ui/seek_to_start_instead_of_rewind.fixed index 15cc8d54faab3..8859a68320f00 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.fixed +++ b/tests/ui/seek_to_start_instead_of_rewind.fixed @@ -80,6 +80,7 @@ fn main() { .write(true) .read(true) .create(true) + .truncate(true) .open("foo.txt") .unwrap(); @@ -104,6 +105,7 @@ fn msrv_1_54() { .write(true) .read(true) .create(true) + .truncate(true) .open("foo.txt") .unwrap(); @@ -124,6 +126,7 @@ fn msrv_1_55() { .write(true) .read(true) .create(true) + .truncate(true) .open("foo.txt") .unwrap(); diff --git a/tests/ui/seek_to_start_instead_of_rewind.rs b/tests/ui/seek_to_start_instead_of_rewind.rs index 197225ffbd5c9..7b72efb34ff82 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.rs +++ b/tests/ui/seek_to_start_instead_of_rewind.rs @@ -80,6 +80,7 @@ fn main() { .write(true) .read(true) .create(true) + .truncate(true) .open("foo.txt") .unwrap(); @@ -104,6 +105,7 @@ fn msrv_1_54() { .write(true) .read(true) .create(true) + .truncate(true) .open("foo.txt") .unwrap(); @@ -124,6 +126,7 @@ fn msrv_1_55() { .write(true) .read(true) .create(true) + .truncate(true) .open("foo.txt") .unwrap(); diff --git a/tests/ui/seek_to_start_instead_of_rewind.stderr b/tests/ui/seek_to_start_instead_of_rewind.stderr index 05c11cf7f8c61..b6b0d2effa815 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.stderr +++ b/tests/ui/seek_to_start_instead_of_rewind.stderr @@ -14,7 +14,7 @@ LL | t.seek(SeekFrom::Start(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()` error: used `seek` to go to the start of the stream - --> $DIR/seek_to_start_instead_of_rewind.rs:133:7 + --> $DIR/seek_to_start_instead_of_rewind.rs:136:7 | LL | f.seek(SeekFrom::Start(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()` From 6fb471d646045ce7c3e81483bc1db2cbb4c9f69c Mon Sep 17 00:00:00 2001 From: atwam Date: Tue, 10 Oct 2023 12:08:17 +0100 Subject: [PATCH 104/676] More helpful text, small style changes. --- clippy_lints/src/methods/mod.rs | 8 ++- clippy_lints/src/methods/open_options.rs | 75 ++++++++++++++---------- clippy_utils/src/paths.rs | 2 + tests/ui/open_options.rs | 1 - tests/ui/open_options.stderr | 35 ++++++----- 5 files changed, 71 insertions(+), 50 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 84fb583595b9c..3d6a16f9ac610 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2829,8 +2829,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for the suspicious use of OpenOptions::create() - /// without an explicit OpenOptions::truncate(). + /// Checks for the suspicious use of `OpenOptions::create()` + /// without an explicit `OpenOptions::truncate()`. /// /// ### Why is this bad? /// create() alone will either create a new file or open an @@ -2850,9 +2850,11 @@ declare_clippy_lint! { /// ```rust /// use std::fs::OpenOptions; /// + /// OpenOptions::new().create(true); + /// /// OpenOptions::new().create(true).truncate(true); /// ``` - #[clippy::version = "1.73.0"] + #[clippy::version = "1.75.0"] pub SUSPICIOUS_OPEN_OPTIONS, suspicious, "suspicious combination of options for opening a file" diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index 81508a5cf65a4..c54a750683662 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -1,6 +1,6 @@ use rustc_data_structures::fx::FxHashMap; -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; @@ -13,7 +13,11 @@ use super::{NONSENSICAL_OPEN_OPTIONS, SUSPICIOUS_OPEN_OPTIONS}; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) && let Some(impl_id) = cx.tcx.impl_of_method(method_id) - && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::FsOpenOptions) + && ( + is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::FsOpenOptions) || + match_type(cx, cx.tcx.type_of(impl_id).instantiate_identity(), &paths::TOKIO_IO_OPEN_OPTIONS) + ) + { let mut options = Vec::new(); get_open_options(cx, recv, &mut options); @@ -49,12 +53,12 @@ impl std::fmt::Display for OpenOption { } } -fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) { - if let ExprKind::MethodCall(path, receiver, arguments, _) = argument.kind { +fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument, Span)>) { + if let ExprKind::MethodCall(path, receiver, arguments, span) = argument.kind { let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); // Only proceed if this is a call on some object of type std::fs::OpenOptions - if is_type_diagnostic_item(cx, obj_ty, sym::FsOpenOptions) && !arguments.is_empty() { + if !arguments.is_empty() && (is_type_diagnostic_item(cx, obj_ty, sym::FsOpenOptions)) { let argument_option = match arguments[0].kind { ExprKind::Lit(span) => { if let Spanned { @@ -74,22 +78,22 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec match path.ident.as_str() { "create" => { - options.push((OpenOption::Create, argument_option)); + options.push((OpenOption::Create, argument_option, span)); }, "create_new" => { - options.push((OpenOption::CreateNew, argument_option)); + options.push((OpenOption::CreateNew, argument_option, span)); }, "append" => { - options.push((OpenOption::Append, argument_option)); + options.push((OpenOption::Append, argument_option, span)); }, "truncate" => { - options.push((OpenOption::Truncate, argument_option)); + options.push((OpenOption::Truncate, argument_option, span)); }, "read" => { - options.push((OpenOption::Read, argument_option)); + options.push((OpenOption::Read, argument_option, span)); }, "write" => { - options.push((OpenOption::Write, argument_option)); + options.push((OpenOption::Write, argument_option, span)); }, _ => (), } @@ -99,24 +103,25 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec } } -fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument)], span: Span) { +fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, Span)], span: Span) { // The args passed to these methods, if they have been called let mut options = FxHashMap::default(); - for (option, arg) in settings { - if options.insert(option.clone(), arg.clone()).is_some() { + for (option, arg, sp) in settings { + if let Some((_, prev_span)) = options.insert(option.clone(), (arg.clone(), *sp)) { span_lint( cx, NONSENSICAL_OPEN_OPTIONS, - span, + prev_span, &format!("the method `{}` is called more than once", &option), ); } } - if let (Some(Argument::Set(true)), Some(Argument::Set(true))) = - (options.get(&OpenOption::Read), options.get(&OpenOption::Truncate)) - { - if options.get(&OpenOption::Write).unwrap_or(&Argument::Set(false)) == &Argument::Set(false) { + if_chain! { + if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Read); + if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate); + if let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Write); + then { span_lint( cx, NONSENSICAL_OPEN_OPTIONS, @@ -126,10 +131,11 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument)], } } - if let (Some(Argument::Set(true)), Some(Argument::Set(true))) = - (options.get(&OpenOption::Append), options.get(&OpenOption::Truncate)) - { - if options.get(&OpenOption::Write).unwrap_or(&Argument::Set(false)) == &Argument::Set(false) { + if_chain! { + if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Append); + if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate); + if let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Write); + then { span_lint( cx, NONSENSICAL_OPEN_OPTIONS, @@ -139,12 +145,21 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument)], } } - if let (Some(Argument::Set(true)), None) = (options.get(&OpenOption::Create), options.get(&OpenOption::Truncate)) { - span_lint( - cx, - SUSPICIOUS_OPEN_OPTIONS, - span, - "file opened with `create`, but `truncate` behavior not defined", - ); + if_chain! { + if let Some((Argument::Set(true), create_span)) = options.get(&OpenOption::Create); + if let None = options.get(&OpenOption::Truncate); + then { + span_lint_and_then( + cx, + SUSPICIOUS_OPEN_OPTIONS, + *create_span, + "file opened with `create`, but `truncate` behavior not defined", + |diag| { + diag + //.span_suggestion(create_span.shrink_to_hi(), "add", ".truncate(true)".to_string(), rustc_errors::Applicability::MaybeIncorrect) + .help("if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`"); + }, + ); + } } } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 0a820a1754cae..2771e49736e61 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -50,6 +50,8 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"]; pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"]; pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"]; +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates +pub const TOKIO_IO_OPEN_OPTIONS: [&str; 3] = ["tokio", "fs", "OpenOptions"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"]; diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index dd380f4101add..3f486b76e723b 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -1,5 +1,4 @@ use std::fs::OpenOptions; - #[allow(unused_must_use)] #[warn(clippy::nonsensical_open_options)] #[warn(clippy::suspicious_open_options)] diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index be6be250f22a3..ecab243069d3b 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -1,5 +1,5 @@ error: file opened with `truncate` and `read` - --> $DIR/open_options.rs:7:5 + --> $DIR/open_options.rs:6:5 | LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,55 +8,58 @@ LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); = help: to override `-D warnings` add `#[allow(clippy::nonsensical_open_options)]` error: file opened with `append` and `truncate` - --> $DIR/open_options.rs:10:5 + --> $DIR/open_options.rs:9:5 | LL | OpenOptions::new().append(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method `read` is called more than once - --> $DIR/open_options.rs:13:5 + --> $DIR/open_options.rs:12:35 | LL | OpenOptions::new().read(true).read(false).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: the method `create` is called more than once - --> $DIR/open_options.rs:15:5 + --> $DIR/open_options.rs:14:37 | LL | OpenOptions::new().create(true).create(false).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: file opened with `create`, but `truncate` behavior not defined - --> $DIR/open_options.rs:15:5 + --> $DIR/open_options.rs:14:24 | LL | OpenOptions::new().create(true).create(false).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | + = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` = note: `-D clippy::suspicious-open-options` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]` error: the method `write` is called more than once - --> $DIR/open_options.rs:17:5 + --> $DIR/open_options.rs:16:36 | LL | OpenOptions::new().write(true).write(false).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error: the method `append` is called more than once - --> $DIR/open_options.rs:19:5 + --> $DIR/open_options.rs:18:37 | LL | OpenOptions::new().append(true).append(false).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: the method `truncate` is called more than once - --> $DIR/open_options.rs:21:5 + --> $DIR/open_options.rs:20:39 | LL | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ error: file opened with `create`, but `truncate` behavior not defined - --> $DIR/open_options.rs:23:5 + --> $DIR/open_options.rs:22:24 | LL | OpenOptions::new().create(true).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ + | + = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` error: aborting due to 9 previous errors From 2ec8729962aae2fc3c72f388a8249e13f241bc20 Mon Sep 17 00:00:00 2001 From: atwam Date: Tue, 10 Oct 2023 13:30:24 +0100 Subject: [PATCH 105/676] PR Fixes --- clippy_lints/src/methods/open_options.rs | 37 +++++++++--------------- tests/ui/open_options.stderr | 12 ++++++-- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index c54a750683662..c006ea192ee53 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -1,6 +1,7 @@ use rustc_data_structures::fx::FxHashMap; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::paths; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; @@ -117,11 +118,10 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S } } - if_chain! { - if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Read); - if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate); - if let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Write); - then { + if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Read) + && let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate) + && let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Write) + { span_lint( cx, NONSENSICAL_OPEN_OPTIONS, @@ -129,37 +129,28 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S "file opened with `truncate` and `read`", ); } - } - if_chain! { - if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Append); - if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate); - if let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Write); - then { + if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Append) + && let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate) + { span_lint( cx, NONSENSICAL_OPEN_OPTIONS, span, "file opened with `append` and `truncate`", ); - } } - if_chain! { - if let Some((Argument::Set(true), create_span)) = options.get(&OpenOption::Create); - if let None = options.get(&OpenOption::Truncate); - then { - span_lint_and_then( + if let Some((Argument::Set(true), create_span)) = options.get(&OpenOption::Create) + && let None = options.get(&OpenOption::Truncate) + { + span_lint_and_help( cx, SUSPICIOUS_OPEN_OPTIONS, *create_span, "file opened with `create`, but `truncate` behavior not defined", - |diag| { - diag - //.span_suggestion(create_span.shrink_to_hi(), "add", ".truncate(true)".to_string(), rustc_errors::Applicability::MaybeIncorrect) - .help("if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`"); - }, + Some(span), + "if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`" ); - } } } diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index ecab243069d3b..11ba7444c97c4 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -31,7 +31,11 @@ error: file opened with `create`, but `truncate` behavior not defined LL | OpenOptions::new().create(true).create(false).open("foo.txt"); | ^^^^^^^^^^^^ | - = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` +help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` + --> $DIR/open_options.rs:14:5 + | +LL | OpenOptions::new().create(true).create(false).open("foo.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `-D clippy::suspicious-open-options` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]` @@ -59,7 +63,11 @@ error: file opened with `create`, but `truncate` behavior not defined LL | OpenOptions::new().create(true).open("foo.txt"); | ^^^^^^^^^^^^ | - = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` +help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` + --> $DIR/open_options.rs:22:5 + | +LL | OpenOptions::new().create(true).open("foo.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 9 previous errors From 84588a8815641a445a29f5fb0ea21767e6e4bbdf Mon Sep 17 00:00:00 2001 From: atwam Date: Thu, 26 Oct 2023 11:30:12 +0100 Subject: [PATCH 106/676] Add suggestion/fix to suspicious_open_options Also rebase and fix conflicts --- clippy_lints/src/methods/open_options.rs | 66 +++++++++++++----------- tests/ui/open_options.rs | 19 +++++-- tests/ui/open_options.stderr | 48 +++++------------ tests/ui/open_options_fixable.fixed | 7 +++ tests/ui/open_options_fixable.rs | 7 +++ tests/ui/open_options_fixable.stderr | 12 +++++ 6 files changed, 89 insertions(+), 70 deletions(-) create mode 100644 tests/ui/open_options_fixable.fixed create mode 100644 tests/ui/open_options_fixable.rs create mode 100644 tests/ui/open_options_fixable.stderr diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index c006ea192ee53..cbe504a9c638b 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -2,23 +2,24 @@ use rustc_data_structures::fx::FxHashMap; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::paths; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{is_type_diagnostic_item, match_type}; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; +use rustc_middle::ty::Ty; use rustc_span::source_map::Spanned; use rustc_span::{sym, Span}; use super::{NONSENSICAL_OPEN_OPTIONS, SUSPICIOUS_OPEN_OPTIONS}; +fn is_open_options(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { + is_type_diagnostic_item(cx, ty, sym::FsOpenOptions) || match_type(cx, ty, &paths::TOKIO_IO_OPEN_OPTIONS) +} + pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) && let Some(impl_id) = cx.tcx.impl_of_method(method_id) - && ( - is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::FsOpenOptions) || - match_type(cx, cx.tcx.type_of(impl_id).instantiate_identity(), &paths::TOKIO_IO_OPEN_OPTIONS) - ) - + && is_open_options(cx, cx.tcx.type_of(impl_id).instantiate_identity()) { let mut options = Vec::new(); get_open_options(cx, recv, &mut options); @@ -59,7 +60,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); // Only proceed if this is a call on some object of type std::fs::OpenOptions - if !arguments.is_empty() && (is_type_diagnostic_item(cx, obj_ty, sym::FsOpenOptions)) { + if !arguments.is_empty() && is_open_options(cx, obj_ty) { let argument_option = match arguments[0].kind { ExprKind::Lit(span) => { if let Spanned { @@ -121,36 +122,39 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Read) && let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate) && let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Write) - { - span_lint( - cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "file opened with `truncate` and `read`", - ); - } + { + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "file opened with `truncate` and `read`", + ); + } if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Append) && let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate) - { - span_lint( - cx, - NONSENSICAL_OPEN_OPTIONS, - span, - "file opened with `append` and `truncate`", - ); + { + span_lint( + cx, + NONSENSICAL_OPEN_OPTIONS, + span, + "file opened with `append` and `truncate`", + ); } if let Some((Argument::Set(true), create_span)) = options.get(&OpenOption::Create) && let None = options.get(&OpenOption::Truncate) - { - span_lint_and_help( - cx, - SUSPICIOUS_OPEN_OPTIONS, - *create_span, - "file opened with `create`, but `truncate` behavior not defined", - Some(span), - "if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`" - ); + { + span_lint_and_then( + cx, + SUSPICIOUS_OPEN_OPTIONS, + *create_span, + "file opened with `create`, but `truncate` behavior not defined", + |diag| { + diag + .span_suggestion(create_span.shrink_to_hi(), "add", ".truncate(true)".to_string(), rustc_errors::Applicability::MaybeIncorrect) + .help("if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`"); + }, + ); } } diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index 3f486b76e723b..726ec1b3ab041 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -1,7 +1,6 @@ use std::fs::OpenOptions; #[allow(unused_must_use)] #[warn(clippy::nonsensical_open_options)] -#[warn(clippy::suspicious_open_options)] fn main() { OpenOptions::new().read(true).truncate(true).open("foo.txt"); //~^ ERROR: file opened with `truncate` and `read` @@ -11,14 +10,24 @@ fn main() { OpenOptions::new().read(true).read(false).open("foo.txt"); //~^ ERROR: the method `read` is called more than once - OpenOptions::new().create(true).create(false).open("foo.txt"); - //~^ ERROR: the method `create` is called more than once + OpenOptions::new() + .create(true) + .truncate(true) // Ensure we don't trigger suspicious open options by having create without truncate + .create(false) + //~^ ERROR: the method `create` is called more than once + .open("foo.txt"); OpenOptions::new().write(true).write(false).open("foo.txt"); //~^ ERROR: the method `write` is called more than once OpenOptions::new().append(true).append(false).open("foo.txt"); //~^ ERROR: the method `append` is called more than once OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); //~^ ERROR: the method `truncate` is called more than once - OpenOptions::new().create(true).open("foo.txt"); - //~^ ERROR: file opened with `create`, but `truncate` behavior not defined + + std::fs::File::options().read(true).read(false).open("foo.txt"); + //~^ ERROR: the method `read` is called more than once + + let mut options = std::fs::OpenOptions::new(); + options.read(true); + options.read(false); + //~^ ERROR: the method `read` is called more than once } diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 11ba7444c97c4..3e7d5a3499d39 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -1,5 +1,5 @@ error: file opened with `truncate` and `read` - --> $DIR/open_options.rs:6:5 + --> $DIR/open_options.rs:5:5 | LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,66 +8,46 @@ LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); = help: to override `-D warnings` add `#[allow(clippy::nonsensical_open_options)]` error: file opened with `append` and `truncate` - --> $DIR/open_options.rs:9:5 + --> $DIR/open_options.rs:8:5 | LL | OpenOptions::new().append(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method `read` is called more than once - --> $DIR/open_options.rs:12:35 + --> $DIR/open_options.rs:11:35 | LL | OpenOptions::new().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^ error: the method `create` is called more than once - --> $DIR/open_options.rs:14:37 + --> $DIR/open_options.rs:16:10 | -LL | OpenOptions::new().create(true).create(false).open("foo.txt"); - | ^^^^^^^^^^^^^ - -error: file opened with `create`, but `truncate` behavior not defined - --> $DIR/open_options.rs:14:24 - | -LL | OpenOptions::new().create(true).create(false).open("foo.txt"); - | ^^^^^^^^^^^^ - | -help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` - --> $DIR/open_options.rs:14:5 - | -LL | OpenOptions::new().create(true).create(false).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: `-D clippy::suspicious-open-options` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]` +LL | .create(false) + | ^^^^^^^^^^^^^ error: the method `write` is called more than once - --> $DIR/open_options.rs:16:36 + --> $DIR/open_options.rs:19:36 | LL | OpenOptions::new().write(true).write(false).open("foo.txt"); | ^^^^^^^^^^^^ error: the method `append` is called more than once - --> $DIR/open_options.rs:18:37 + --> $DIR/open_options.rs:21:37 | LL | OpenOptions::new().append(true).append(false).open("foo.txt"); | ^^^^^^^^^^^^^ error: the method `truncate` is called more than once - --> $DIR/open_options.rs:20:39 + --> $DIR/open_options.rs:23:39 | LL | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^ -error: file opened with `create`, but `truncate` behavior not defined - --> $DIR/open_options.rs:22:24 - | -LL | OpenOptions::new().create(true).open("foo.txt"); - | ^^^^^^^^^^^^ - | -help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` - --> $DIR/open_options.rs:22:5 +error: the method `read` is called more than once + --> $DIR/open_options.rs:26:41 | -LL | OpenOptions::new().create(true).open("foo.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | std::fs::File::options().read(true).read(false).open("foo.txt"); + | ^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/open_options_fixable.fixed b/tests/ui/open_options_fixable.fixed new file mode 100644 index 0000000000000..90a129a9bdffd --- /dev/null +++ b/tests/ui/open_options_fixable.fixed @@ -0,0 +1,7 @@ +use std::fs::OpenOptions; +#[allow(unused_must_use)] +#[warn(clippy::suspicious_open_options)] +fn main() { + OpenOptions::new().create(true).truncate(true).open("foo.txt"); + //~^ ERROR: file opened with `create`, but `truncate` behavior not defined +} diff --git a/tests/ui/open_options_fixable.rs b/tests/ui/open_options_fixable.rs new file mode 100644 index 0000000000000..3a9e522ba1507 --- /dev/null +++ b/tests/ui/open_options_fixable.rs @@ -0,0 +1,7 @@ +use std::fs::OpenOptions; +#[allow(unused_must_use)] +#[warn(clippy::suspicious_open_options)] +fn main() { + OpenOptions::new().create(true).open("foo.txt"); + //~^ ERROR: file opened with `create`, but `truncate` behavior not defined +} diff --git a/tests/ui/open_options_fixable.stderr b/tests/ui/open_options_fixable.stderr new file mode 100644 index 0000000000000..1ef49c54afc21 --- /dev/null +++ b/tests/ui/open_options_fixable.stderr @@ -0,0 +1,12 @@ +error: file opened with `create`, but `truncate` behavior not defined + --> $DIR/open_options_fixable.rs:5:24 + | +LL | OpenOptions::new().create(true).open("foo.txt"); + | ^^^^^^^^^^^^- help: add: `.truncate(true)` + | + = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` + = note: `-D clippy::suspicious-open-options` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]` + +error: aborting due to previous error + From 515fe65ba8f1006bec5e4e906aaeb345b05834bc Mon Sep 17 00:00:00 2001 From: atwam Date: Thu, 11 Jan 2024 12:49:49 +0000 Subject: [PATCH 107/676] Fix conflicts - New ineffective_open_options had to be fixed. - Now not raising an issue on missing `truncate` when `append(true)` makes the intent clear. - Try implementing more advanced tests for non-chained operations. Fail --- clippy_lints/src/methods/open_options.rs | 31 ++++++++++++++++++------ tests/ui/ineffective_open_options.fixed | 9 ++++++- tests/ui/ineffective_open_options.rs | 9 ++++++- tests/ui/open_options.rs | 3 ++- tests/ui/open_options_fixable.stderr | 4 +-- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index cbe504a9c638b..d45ba2a772857 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -1,8 +1,8 @@ use rustc_data_structures::fx::FxHashMap; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::paths; use clippy_utils::ty::{is_type_diagnostic_item, match_type}; +use clippy_utils::{match_any_def_paths, paths}; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -19,7 +19,7 @@ fn is_open_options(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) && let Some(impl_id) = cx.tcx.impl_of_method(method_id) - && is_open_options(cx, cx.tcx.type_of(impl_id).instantiate_identity()) + //&& is_open_options(cx, cx.tcx.type_of(impl_id).instantiate_identity()) { let mut options = Vec::new(); get_open_options(cx, recv, &mut options); @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx } } -#[derive(Eq, PartialEq, Clone)] +#[derive(Eq, PartialEq, Clone, Debug)] enum Argument { Set(bool), Unknown, @@ -55,7 +55,11 @@ impl std::fmt::Display for OpenOption { } } -fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument, Span)>) { +fn get_open_options( + cx: &LateContext<'_>, + argument: &Expr<'_>, + options: &mut Vec<(OpenOption, Argument, Span)>, +) -> bool { if let ExprKind::MethodCall(path, receiver, arguments, span) = argument.kind { let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); @@ -72,7 +76,8 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec } else { // The function is called with a literal which is not a boolean literal. // This is theoretically possible, but not very likely. - return; + // We'll ignore it for now + return get_open_options(cx, receiver, options); } }, _ => Argument::Unknown, @@ -100,8 +105,19 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec _ => (), } - get_open_options(cx, receiver, options); + get_open_options(cx, receiver, options) + } else { + false } + } else if let ExprKind::Call(callee, _) = argument.kind + && let ExprKind::Path(path) = callee.kind + && let Some(did) = cx.qpath_res(&path, callee.hir_id).opt_def_id() + { + match_any_def_paths(cx, did, &[&paths::TOKIO_IO_OPEN_OPTIONS]).is_some() + //is_type_diagnostic_item(cx, ty, sym::FsOpenOptions) || match_type(cx, ty, + // &paths::TOKIO_IO_OPEN_OPTIONS) + } else { + false } } @@ -144,6 +160,7 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S if let Some((Argument::Set(true), create_span)) = options.get(&OpenOption::Create) && let None = options.get(&OpenOption::Truncate) + && let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Append) { span_lint_and_then( cx, @@ -153,7 +170,7 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S |diag| { diag .span_suggestion(create_span.shrink_to_hi(), "add", ".truncate(true)".to_string(), rustc_errors::Applicability::MaybeIncorrect) - .help("if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`"); + .help("if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`. Alternatively, use `.append` to append to the file instead of overwriting it."); }, ); } diff --git a/tests/ui/ineffective_open_options.fixed b/tests/ui/ineffective_open_options.fixed index 3af8f3c5aaa44..88489dc46bbb4 100644 --- a/tests/ui/ineffective_open_options.fixed +++ b/tests/ui/ineffective_open_options.fixed @@ -26,16 +26,23 @@ fn main() { .unwrap(); let file = OpenOptions::new() .create(true) + .truncate(true) .write(true) .append(false) .open("dump.json") .unwrap(); let file = OpenOptions::new() .create(true) + .truncate(true) .write(false) .append(false) .open("dump.json") .unwrap(); let file = OpenOptions::new().create(true).append(true).open("dump.json").unwrap(); - let file = OpenOptions::new().create(true).write(true).open("dump.json").unwrap(); + let file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open("dump.json") + .unwrap(); } diff --git a/tests/ui/ineffective_open_options.rs b/tests/ui/ineffective_open_options.rs index 4eaf6293c408e..db8bca3e2acdb 100644 --- a/tests/ui/ineffective_open_options.rs +++ b/tests/ui/ineffective_open_options.rs @@ -26,16 +26,23 @@ fn main() { .unwrap(); let file = OpenOptions::new() .create(true) + .truncate(true) .write(true) .append(false) .open("dump.json") .unwrap(); let file = OpenOptions::new() .create(true) + .truncate(true) .write(false) .append(false) .open("dump.json") .unwrap(); let file = OpenOptions::new().create(true).append(true).open("dump.json").unwrap(); - let file = OpenOptions::new().create(true).write(true).open("dump.json").unwrap(); + let file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open("dump.json") + .unwrap(); } diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index 726ec1b3ab041..873094dd7245f 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -29,5 +29,6 @@ fn main() { let mut options = std::fs::OpenOptions::new(); options.read(true); options.read(false); - //~^ ERROR: the method `read` is called more than once + //#~^ ERROR: the method `read` is called more than once + options.open("foo.txt"); } diff --git a/tests/ui/open_options_fixable.stderr b/tests/ui/open_options_fixable.stderr index 1ef49c54afc21..de88af87cd41a 100644 --- a/tests/ui/open_options_fixable.stderr +++ b/tests/ui/open_options_fixable.stderr @@ -4,9 +4,9 @@ error: file opened with `create`, but `truncate` behavior not defined LL | OpenOptions::new().create(true).open("foo.txt"); | ^^^^^^^^^^^^- help: add: `.truncate(true)` | - = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` + = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`. Alternatively, use `.append` to append to the file instead of overwriting it. = note: `-D clippy::suspicious-open-options` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]` -error: aborting due to previous error +error: aborting due to 1 previous error From f09cd88199e730e63a4ffb5df4ea13d64c834e2d Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 14 Jan 2024 00:11:42 +0100 Subject: [PATCH 108/676] fix false positive in `suspicious_open_options`, make paths work --- clippy_lints/src/methods/mod.rs | 11 ++++-- clippy_lints/src/methods/open_options.rs | 49 +++++++++++++++++++----- clippy_utils/src/paths.rs | 10 ++++- tests/ui/open_options.rs | 24 ++++++++++-- tests/ui/open_options.stderr | 16 ++++---- tests/ui/open_options_fixable.stderr | 4 +- 6 files changed, 87 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 3d6a16f9ac610..03bcf108914a0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2833,10 +2833,11 @@ declare_clippy_lint! { /// without an explicit `OpenOptions::truncate()`. /// /// ### Why is this bad? - /// create() alone will either create a new file or open an + /// `create()` alone will either create a new file or open an /// existing file. If the file already exists, it will be /// overwritten when written to, but the file will not be - /// truncated by default. If less data is written to the file + /// truncated by default. + /// If less data is written to the file /// than it already contains, the remainder of the file will /// remain unchanged, and the end of the file will contain old /// data. @@ -2847,10 +2848,14 @@ declare_clippy_lint! { /// `truncate(false)` will explicitely keep the default behavior. /// /// ### Example - /// ```rust + /// ```rust,no_run /// use std::fs::OpenOptions; /// /// OpenOptions::new().create(true); + /// ``` + /// Use instead: + /// ```rust,no_run + /// use std::fs::OpenOptions; /// /// OpenOptions::new().create(true).truncate(true); /// ``` diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index d45ba2a772857..77484ab91a9d7 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -19,11 +19,12 @@ fn is_open_options(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) && let Some(impl_id) = cx.tcx.impl_of_method(method_id) - //&& is_open_options(cx, cx.tcx.type_of(impl_id).instantiate_identity()) + && is_open_options(cx, cx.tcx.type_of(impl_id).instantiate_identity()) { let mut options = Vec::new(); - get_open_options(cx, recv, &mut options); - check_open_options(cx, &options, e.span); + if get_open_options(cx, recv, &mut options) { + check_open_options(cx, &options, e.span); + } } } @@ -55,6 +56,9 @@ impl std::fmt::Display for OpenOption { } } +/// Collects information about a method call chain on `OpenOptions`. +/// Returns false if an unexpected expression kind was found "on the way", +/// and linting should then be avoided. fn get_open_options( cx: &LateContext<'_>, argument: &Expr<'_>, @@ -102,7 +106,16 @@ fn get_open_options( "write" => { options.push((OpenOption::Write, argument_option, span)); }, - _ => (), + _ => { + // Avoid linting altogether if this method is from a trait. + // This might be a user defined extension trait with a method like `truncate_write` + // which would be a false positive + if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(argument.hir_id) + && cx.tcx.trait_of_item(method_def_id).is_some() + { + return false; + } + }, } get_open_options(cx, receiver, options) @@ -113,9 +126,17 @@ fn get_open_options( && let ExprKind::Path(path) = callee.kind && let Some(did) = cx.qpath_res(&path, callee.hir_id).opt_def_id() { - match_any_def_paths(cx, did, &[&paths::TOKIO_IO_OPEN_OPTIONS]).is_some() - //is_type_diagnostic_item(cx, ty, sym::FsOpenOptions) || match_type(cx, ty, - // &paths::TOKIO_IO_OPEN_OPTIONS) + match_any_def_paths( + cx, + did, + &[ + &paths::TOKIO_IO_OPEN_OPTIONS_NEW, + &paths::OPEN_OPTIONS_NEW, + &paths::FILE_OPTIONS, + &paths::TOKIO_FILE_OPTIONS, + ], + ) + .is_some() } else { false } @@ -168,9 +189,17 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S *create_span, "file opened with `create`, but `truncate` behavior not defined", |diag| { - diag - .span_suggestion(create_span.shrink_to_hi(), "add", ".truncate(true)".to_string(), rustc_errors::Applicability::MaybeIncorrect) - .help("if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`. Alternatively, use `.append` to append to the file instead of overwriting it."); + diag.span_suggestion( + create_span.shrink_to_hi(), + "add", + ".truncate(true)".to_string(), + rustc_errors::Applicability::MaybeIncorrect, + ) + .help("if you intend to overwrite an existing file entirely, call `.truncate(true)`") + .help( + "if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`", + ) + .help("alternatively, use `.append(true)` to append to the file instead of overwriting it"); }, ); } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 2771e49736e61..0051f78451467 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -26,6 +26,7 @@ pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"]; pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"]; pub const F32_EPSILON: [&str; 4] = ["core", "f32", "", "EPSILON"]; pub const F64_EPSILON: [&str; 4] = ["core", "f64", "", "EPSILON"]; +pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates @@ -50,8 +51,7 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"]; pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"]; pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"]; -#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates -pub const TOKIO_IO_OPEN_OPTIONS: [&str; 3] = ["tokio", "fs", "OpenOptions"]; +pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"]; @@ -91,9 +91,15 @@ pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"]; pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates +pub const TOKIO_FILE_OPTIONS: [&str; 5] = ["tokio", "fs", "file", "File", "options"]; +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_write_ext", "AsyncWriteExt"]; +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates +pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "OpenOptions"]; +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates +pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"]; pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"]; pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"]; pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"]; diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index 873094dd7245f..4acb3780df43e 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -1,6 +1,18 @@ +#![allow(unused_must_use)] +#![warn(clippy::nonsensical_open_options)] + use std::fs::OpenOptions; -#[allow(unused_must_use)] -#[warn(clippy::nonsensical_open_options)] + +trait OpenOptionsExt { + fn truncate_write(&mut self, opt: bool) -> &mut Self; +} + +impl OpenOptionsExt for OpenOptions { + fn truncate_write(&mut self, opt: bool) -> &mut Self { + self.truncate(opt).write(opt) + } +} + fn main() { OpenOptions::new().read(true).truncate(true).open("foo.txt"); //~^ ERROR: file opened with `truncate` and `read` @@ -29,6 +41,12 @@ fn main() { let mut options = std::fs::OpenOptions::new(); options.read(true); options.read(false); - //#~^ ERROR: the method `read` is called more than once + // Possible future improvement: recognize open options method call chains across statements. options.open("foo.txt"); + + let mut options = std::fs::OpenOptions::new(); + options.truncate(true); + options.create(true).open("foo.txt"); + + OpenOptions::new().create(true).truncate_write(true).open("foo.txt"); } diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 3e7d5a3499d39..4f84d1d09f984 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -1,5 +1,5 @@ error: file opened with `truncate` and `read` - --> $DIR/open_options.rs:5:5 + --> $DIR/open_options.rs:17:5 | LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,43 +8,43 @@ LL | OpenOptions::new().read(true).truncate(true).open("foo.txt"); = help: to override `-D warnings` add `#[allow(clippy::nonsensical_open_options)]` error: file opened with `append` and `truncate` - --> $DIR/open_options.rs:8:5 + --> $DIR/open_options.rs:20:5 | LL | OpenOptions::new().append(true).truncate(true).open("foo.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the method `read` is called more than once - --> $DIR/open_options.rs:11:35 + --> $DIR/open_options.rs:23:35 | LL | OpenOptions::new().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^ error: the method `create` is called more than once - --> $DIR/open_options.rs:16:10 + --> $DIR/open_options.rs:28:10 | LL | .create(false) | ^^^^^^^^^^^^^ error: the method `write` is called more than once - --> $DIR/open_options.rs:19:36 + --> $DIR/open_options.rs:31:36 | LL | OpenOptions::new().write(true).write(false).open("foo.txt"); | ^^^^^^^^^^^^ error: the method `append` is called more than once - --> $DIR/open_options.rs:21:37 + --> $DIR/open_options.rs:33:37 | LL | OpenOptions::new().append(true).append(false).open("foo.txt"); | ^^^^^^^^^^^^^ error: the method `truncate` is called more than once - --> $DIR/open_options.rs:23:39 + --> $DIR/open_options.rs:35:39 | LL | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^ error: the method `read` is called more than once - --> $DIR/open_options.rs:26:41 + --> $DIR/open_options.rs:38:41 | LL | std::fs::File::options().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^ diff --git a/tests/ui/open_options_fixable.stderr b/tests/ui/open_options_fixable.stderr index de88af87cd41a..e327661713bfb 100644 --- a/tests/ui/open_options_fixable.stderr +++ b/tests/ui/open_options_fixable.stderr @@ -4,7 +4,9 @@ error: file opened with `create`, but `truncate` behavior not defined LL | OpenOptions::new().create(true).open("foo.txt"); | ^^^^^^^^^^^^- help: add: `.truncate(true)` | - = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`. if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`. Alternatively, use `.append` to append to the file instead of overwriting it. + = help: if you intend to overwrite an existing file entirely, call `.truncate(true)` + = help: if you instead know that you may want to keep some parts of the old file, call `.truncate(false)` + = help: alternatively, use `.append(true)` to append to the file instead of overwriting it = note: `-D clippy::suspicious-open-options` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]` From ad2a2ba94dea6a7b498a0ad85bcb10aac44b95c1 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Mon, 15 Jan 2024 12:26:45 -0500 Subject: [PATCH 109/676] Ensure `callee_id`s are body owners --- clippy_lints/src/derive.rs | 4 +-- clippy_lints/src/loops/explicit_iter_loop.rs | 2 +- clippy_utils/src/ty.rs | 30 +++++++------------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index d8abe411030b6..a8217d0602a56 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -450,12 +450,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) - && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[]) + && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[]) // If all of our fields implement `Eq`, we can implement `Eq` too && adt .all_fields() .map(|f| f.ty(cx.tcx, args)) - .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[])) + .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])) { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index c7980060807c3..814ccaa36f5aa 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>( .liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output && let param_env = cx.tcx.param_env(fn_id) - && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[]) + && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[]) && let Some(into_iter_ty) = make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty]) && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty) diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 61d0663aa8399..a07d6587bf97c 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -214,36 +214,21 @@ pub fn implements_trait<'tcx>( trait_id: DefId, args: &[GenericArg<'tcx>], ) -> bool { - let callee_id = cx - .enclosing_body - .map(|body| cx.tcx.hir().body_owner(body).owner.to_def_id()); - implements_trait_with_env_from_iter( - cx.tcx, - cx.param_env, - ty, - trait_id, - callee_id, - args.iter().map(|&x| Some(x)), - ) + implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, None, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. +/// +/// The `callee_id` argument is used to determine the "effect arg", if one is needed. pub fn implements_trait_with_env<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, - callee_id: DefId, + callee_id: Option, args: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env_from_iter( - tcx, - param_env, - ty, - trait_id, - Some(callee_id), - args.iter().map(|&x| Some(x)), - ) + implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait_from_env` but takes the arguments as an iterator. @@ -258,6 +243,11 @@ pub fn implements_trait_with_env_from_iter<'tcx>( // Clippy shouldn't have infer types assert!(!ty.has_infer()); + // If a `callee_id` is passed, then "assert" it is a body owner. + if let Some(callee_id) = callee_id { + let _ = tcx.hir().body_owner_kind(callee_id); + } + let ty = tcx.erase_regions(ty); if ty.has_escaping_bound_vars() { return false; From 6a74a0e17ba5e13df18efe4cb77283a9a60065f1 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 12 Jan 2024 08:21:42 +0100 Subject: [PATCH 110/676] compiler: Lower fn call arg spans down to MIR To enable improved accuracy of diagnostics in upcoming commits. --- clippy_lints/src/redundant_clone.rs | 4 ++-- clippy_utils/src/mir/possible_borrower.rs | 2 +- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index c62c351e71670..3416a93e3c4ac 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -257,9 +257,9 @@ fn is_call_with_ref_arg<'tcx>( .. } = kind && args.len() == 1 - && let mir::Operand::Move(mir::Place { local, .. }) = &args[0] + && let mir::Operand::Move(mir::Place { local, .. }) = &args[0].node && let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind() - && let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx)) + && let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].node.ty(mir, cx.tcx)) && !is_copy(cx, inner_ty) { Some((def_id, *local, inner_ty, destination.as_local()?)) diff --git a/clippy_utils/src/mir/possible_borrower.rs b/clippy_utils/src/mir/possible_borrower.rs index 703985b9d4b3f..f9cc5f191253a 100644 --- a/clippy_utils/src/mir/possible_borrower.rs +++ b/clippy_utils/src/mir/possible_borrower.rs @@ -104,7 +104,7 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, let mut mutable_borrowers = vec![]; for op in args { - match op { + match &op.node { mir::Operand::Copy(p) | mir::Operand::Move(p) => { if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() { mutable_borrowers.push(p.local); diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 668ea9fcf3b4b..81f4fcc2133d1 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -345,7 +345,7 @@ fn check_terminator<'tcx>( check_operand(tcx, func, span, body)?; for arg in args { - check_operand(tcx, arg, span, body)?; + check_operand(tcx, &arg.node, span, body)?; } Ok(()) } else { From f40f99656228b4c7e91accb8524a51482bf84974 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 12 Jan 2024 08:21:42 +0100 Subject: [PATCH 111/676] compiler: Lower fn call arg spans down to MIR To enable improved accuracy of diagnostics in upcoming commits. --- src/abi/mod.rs | 13 ++--- src/intrinsics/llvm.rs | 2 +- src/intrinsics/llvm_aarch64.rs | 2 +- src/intrinsics/llvm_x86.rs | 86 +++++++++++++++++----------------- src/intrinsics/mod.rs | 22 +++++---- src/intrinsics/simd.rs | 24 +++++----- 6 files changed, 77 insertions(+), 72 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 795c8daec6a34..abd70dd4458f6 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -11,6 +11,7 @@ use cranelift_module::ModuleError; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::FnAbiOf; use rustc_session::Session; +use rustc_span::source_map::Spanned; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; @@ -360,7 +361,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, source_info: mir::SourceInfo, func: &Operand<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], destination: Place<'tcx>, target: Option, ) { @@ -415,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let extra_args = &args[fn_sig.inputs().skip_binder().len()..]; let extra_args = fx.tcx.mk_type_list_from_iter( - extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))), + extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.node.ty(fx.mir, fx.tcx))), ); let fn_abi = if let Some(instance) = instance { RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args) @@ -440,10 +441,10 @@ pub(crate) fn codegen_terminator_call<'tcx>( // Unpack arguments tuple for closures let mut args = if fn_sig.abi() == Abi::RustCall { let (self_arg, pack_arg) = match args { - [pack_arg] => (None, codegen_call_argument_operand(fx, pack_arg)), + [pack_arg] => (None, codegen_call_argument_operand(fx, &pack_arg.node)), [self_arg, pack_arg] => ( - Some(codegen_call_argument_operand(fx, self_arg)), - codegen_call_argument_operand(fx, pack_arg), + Some(codegen_call_argument_operand(fx, &self_arg.node)), + codegen_call_argument_operand(fx, &pack_arg.node), ), _ => panic!("rust-call abi requires one or two arguments"), }; @@ -463,7 +464,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } args } else { - args.iter().map(|arg| codegen_call_argument_operand(fx, arg)).collect::>() + args.iter().map(|arg| codegen_call_argument_operand(fx, &arg.node)).collect::>() }; // Pass the caller location for `#[track_caller]`. diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index a38a728c926d8..1345c4614e254 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -7,7 +7,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, span: Span, diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index c8f9c3997a63f..f6f3b85d3ef81 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -7,7 +7,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, _args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, ) { diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 81114cbf40d83..994dc66835cde 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -11,7 +11,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, _args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, span: Span, @@ -175,9 +175,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [x, y, kind] => (x, y, kind), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); - let kind = match kind { + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); + let kind = match &kind.node { Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, Operand::Copy(_) | Operand::Move(_) => unreachable!("{kind:?}"), }; @@ -287,8 +287,8 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [a, b] => (a, b), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let a = codegen_operand(fx, a); - let b = codegen_operand(fx, b); + let a = codegen_operand(fx, &a.node); + let b = codegen_operand(fx, &b.node); // Based on the pseudocode at https://github.com/rust-lang/stdarch/blob/1cfbca8b38fd9b4282b2f054f61c6ca69fc7ce29/crates/core_arch/src/x86/avx2.rs#L2319-L2332 let zero = fx.bcx.ins().iconst(types::I8, 0); @@ -325,9 +325,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [a, b, imm8] => (a, b, imm8), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let a = codegen_operand(fx, a); - let b = codegen_operand(fx, b); - let imm8 = codegen_operand(fx, imm8).load_scalar(fx); + let a = codegen_operand(fx, &a.node); + let b = codegen_operand(fx, &b.node); + let imm8 = codegen_operand(fx, &imm8.node).load_scalar(fx); let a_low = a.value_typed_lane(fx, fx.tcx.types.u128, 0).load_scalar(fx); let a_high = a.value_typed_lane(fx, fx.tcx.types.u128, 1).load_scalar(fx); @@ -956,14 +956,14 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let b = b.load_scalar(fx); let lb = lb.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4]) - { - imm8 - } else { - fx.tcx - .dcx() - .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant"); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4].node) { + imm8 + } else { + fx.tcx + .dcx() + .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant"); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1009,14 +1009,14 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let b = b.load_scalar(fx); let lb = lb.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4]) - { - imm8 - } else { - fx.tcx - .dcx() - .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant"); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4].node) { + imm8 + } else { + fx.tcx + .dcx() + .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant"); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1056,15 +1056,15 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let a = a.load_scalar(fx); let b = b.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2]) - { - imm8 - } else { - fx.tcx.dcx().span_fatal( - span, - "Index argument for `_mm_clmulepi64_si128` is not a constant", - ); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2].node) { + imm8 + } else { + fx.tcx.dcx().span_fatal( + span, + "Index argument for `_mm_clmulepi64_si128` is not a constant", + ); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1093,15 +1093,15 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let a = a.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1]) - { - imm8 - } else { - fx.tcx.dcx().span_fatal( - span, - "Index argument for `_mm_aeskeygenassist_si128` is not a constant", - ); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1].node) { + imm8 + } else { + fx.tcx.dcx().span_fatal( + span, + "Index argument for `_mm_aeskeygenassist_si128` is not a constant", + ); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 15249402a63e7..a27853fa0a82c 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -5,7 +5,7 @@ macro_rules! intrinsic_args { ($fx:expr, $args:expr => ($($arg:tt),*); $intrinsic:expr) => { #[allow(unused_parens)] let ($($arg),*) = if let [$($arg),*] = $args { - ($(codegen_operand($fx, $arg)),*) + ($(codegen_operand($fx, &($arg).node)),*) } else { $crate::intrinsics::bug_on_incorrect_arg_count($intrinsic); }; @@ -22,6 +22,7 @@ use rustc_middle::ty; use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::GenericArgsRef; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; pub(crate) use self::llvm::codegen_llvm_intrinsic_call; @@ -263,7 +264,7 @@ fn bool_to_zero_or_max_uint<'tcx>( pub(crate) fn codegen_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, instance: Instance<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], destination: CPlace<'tcx>, target: Option, source_info: mir::SourceInfo, @@ -301,7 +302,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( fn codegen_float_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, ) -> bool { let (name, arg_count, ty, clif_ty) = match intrinsic { @@ -353,18 +354,21 @@ fn codegen_float_intrinsic_call<'tcx>( let (a, b, c); let args = match args { [x] => { - a = [codegen_operand(fx, x).load_scalar(fx)]; + a = [codegen_operand(fx, &x.node).load_scalar(fx)]; &a as &[_] } [x, y] => { - b = [codegen_operand(fx, x).load_scalar(fx), codegen_operand(fx, y).load_scalar(fx)]; + b = [ + codegen_operand(fx, &x.node).load_scalar(fx), + codegen_operand(fx, &y.node).load_scalar(fx), + ]; &b } [x, y, z] => { c = [ - codegen_operand(fx, x).load_scalar(fx), - codegen_operand(fx, y).load_scalar(fx), - codegen_operand(fx, z).load_scalar(fx), + codegen_operand(fx, &x.node).load_scalar(fx), + codegen_operand(fx, &y.node).load_scalar(fx), + codegen_operand(fx, &z.node).load_scalar(fx), ]; &c } @@ -422,7 +426,7 @@ fn codegen_regular_intrinsic_call<'tcx>( instance: Instance<'tcx>, intrinsic: Symbol, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, destination: Option, source_info: mir::SourceInfo, diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 78ea7c2dbfc39..d56d17892d5b6 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -21,7 +21,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: BasicBlock, span: Span, @@ -121,8 +121,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let [x, y] = args else { bug!("wrong number of args for intrinsic {intrinsic}"); }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); @@ -172,8 +172,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); @@ -182,7 +182,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic. - let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); + let idx_ty = fx.monomorphize(idx.node.ty(fx.mir, fx.tcx)); let n: u16 = match idx_ty.kind() { ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) @@ -215,7 +215,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; - let idx_const = match idx { + let idx_const = match &idx.node { Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, Operand::Copy(_) | Operand::Move(_) => unreachable!("{idx:?}"), }; @@ -269,12 +269,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let base = codegen_operand(fx, base); - let val = codegen_operand(fx, val); + let base = codegen_operand(fx, &base.node); + let val = codegen_operand(fx, &val.node); // FIXME validate let idx_const = if let Some(idx_const) = - crate::constant::mir_operand_get_const_val(fx, idx) + crate::constant::mir_operand_get_const_val(fx, &idx.node) { idx_const } else { @@ -304,7 +304,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let v = codegen_operand(fx, v); + let v = codegen_operand(fx, &v.node); if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); @@ -312,7 +312,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } let idx_const = if let Some(idx_const) = - crate::constant::mir_operand_get_const_val(fx, idx) + crate::constant::mir_operand_get_const_val(fx, &idx.node) { idx_const } else { From 874f851ac5d82a5e2c68e46ddf850b8047f40415 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 15 Jan 2024 20:53:00 +0100 Subject: [PATCH 112/676] Use `std_or_core` instead of doing check by hand every time --- .../src/default_instead_of_iter_empty.rs | 11 ++++------- clippy_lints/src/mem_replace.rs | 16 ++++++---------- .../iter_on_single_or_empty_collections.rs | 4 ++-- clippy_lints/src/operators/ptr_eq.rs | 4 ++-- .../src/transmute/transmute_int_to_char.rs | 8 +++----- .../src/transmute/transmute_ref_to_ref.rs | 6 +++--- 6 files changed, 20 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs index 7287b3fcec9b7..e617c19eff09b 100644 --- a/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/clippy_lints/src/default_instead_of_iter_empty.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; -use clippy_utils::{is_no_std_crate, last_path_segment}; +use clippy_utils::{last_path_segment, std_or_core}; use rustc_errors::Applicability; use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -42,12 +42,9 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty { && ty.span.ctxt() == ctxt { let mut applicability = Applicability::MachineApplicable; - let path = if is_no_std_crate(cx) { - "core::iter::empty" - } else { - "std::iter::empty" - }; - let sugg = make_sugg(cx, ty_path, ctxt, &mut applicability, path); + let Some(path) = std_or_core(cx) else { return }; + let path = format!("{path}::iter::empty"); + let sugg = make_sugg(cx, ty_path, ctxt, &mut applicability, &path); span_lint_and_sugg( cx, DEFAULT_INSTEAD_OF_ITER_EMPTY, diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 919a959073a7f..fa4f4a47e38e2 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lin use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_non_aggregate_primitive_type; -use clippy_utils::{is_default_equivalent, is_no_std_crate, is_res_lang_ctor, path_res, peel_ref_operators}; +use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators, std_or_core}; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; use rustc_hir::{Expr, ExprKind}; @@ -123,15 +123,12 @@ fn check_replace_option_with_none(cx: &LateContext<'_>, dest: &Expr<'_>, expr_sp ); } -fn get_top_crate(cx: &LateContext<'_>) -> &'static str { - if is_no_std_crate(cx) { "core" } else { "std" } -} - fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(src.hir_id) // check if replacement is mem::MaybeUninit::uninit().assume_init() && cx.tcx.is_diagnostic_item(sym::assume_init, method_def_id) { + let Some(top_crate) = std_or_core(cx) else { return }; let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, @@ -140,8 +137,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' "replacing with `mem::MaybeUninit::uninit().assume_init()`", "consider using", format!( - "{}::ptr::read({})", - get_top_crate(cx), + "{top_crate}::ptr::read({})", snippet_with_applicability(cx, dest.span, "", &mut applicability) ), applicability, @@ -154,6 +150,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id() { if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) { + let Some(top_crate) = std_or_core(cx) else { return }; let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, @@ -162,8 +159,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' "replacing with `mem::uninitialized()`", "consider using", format!( - "{}::ptr::read({})", - get_top_crate(cx), + "{top_crate}::ptr::read({})", snippet_with_applicability(cx, dest.span, "", &mut applicability) ), applicability, @@ -190,7 +186,7 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr< return; } if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) { - let top_crate = get_top_crate(cx); + let Some(top_crate) = std_or_core(cx) else { return }; span_lint_and_then( cx, MEM_REPLACE_WITH_DEFAULT, diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index e1ed272231a38..4c7c56e7174a0 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use clippy_utils::{get_expr_use_or_unification_node, is_no_std_crate, is_res_lang_ctor, path_res}; +use clippy_utils::{get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core}; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; @@ -58,7 +58,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re return; } - let top_crate = if is_no_std_crate(cx) { "core" } else { "std" }; + let Some(top_crate) = std_or_core(cx) else { return }; if let Some(i) = item { let sugg = format!( "{top_crate}::iter::once({}{})", diff --git a/clippy_lints/src/operators/ptr_eq.rs b/clippy_lints/src/operators/ptr_eq.rs index 31b51193fb159..a69989e400be4 100644 --- a/clippy_lints/src/operators/ptr_eq.rs +++ b/clippy_lints/src/operators/ptr_eq.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_no_std_crate; use clippy_utils::source::snippet_opt; +use clippy_utils::std_or_core; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>( && let Some(left_snip) = snippet_opt(cx, left_var.span) && let Some(right_snip) = snippet_opt(cx, right_var.span) { - let top_crate = if is_no_std_crate(cx) { "core" } else { "std" }; + let Some(top_crate) = std_or_core(cx) else { return }; span_lint_and_sugg( cx, PTR_EQ, diff --git a/clippy_lints/src/transmute/transmute_int_to_char.rs b/clippy_lints/src/transmute/transmute_int_to_char.rs index 71e8a26a566d3..2a6c248125459 100644 --- a/clippy_lints/src/transmute/transmute_int_to_char.rs +++ b/clippy_lints/src/transmute/transmute_int_to_char.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_INT_TO_CHAR; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{is_no_std_crate, sugg}; +use clippy_utils::{std_or_core, sugg}; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::Expr; @@ -25,6 +25,7 @@ pub(super) fn check<'tcx>( e.span, &format!("transmute from a `{from_ty}` to a `char`"), |diag| { + let Some(top_crate) = std_or_core(cx) else { return }; let arg = sugg::Sugg::hir(cx, arg, ".."); let arg = if let ty::Int(_) = from_ty.kind() { arg.as_ty(ast::UintTy::U32.name_str()) @@ -34,10 +35,7 @@ pub(super) fn check<'tcx>( diag.span_suggestion( e.span, "consider using", - format!( - "{}::char::from_u32({arg}).unwrap()", - if is_no_std_crate(cx) { "core" } else { "std" } - ), + format!("{top_crate}::char::from_u32({arg}).unwrap()"), Applicability::Unspecified, ); }, diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs index c923b4b6dd4a9..6c885ebdea11d 100644 --- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -1,7 +1,7 @@ use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet; -use clippy_utils::{is_no_std_crate, sugg}; +use clippy_utils::{std_or_core, sugg}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; @@ -25,12 +25,12 @@ pub(super) fn check<'tcx>( && let ty::Uint(ty::UintTy::U8) = slice_ty.kind() && from_mutbl == to_mutbl { + let Some(top_crate) = std_or_core(cx) else { return true }; + let postfix = if *from_mutbl == Mutability::Mut { "_mut" } else { "" }; let snippet = snippet(cx, arg.span, ".."); - let top_crate = if is_no_std_crate(cx) { "core" } else { "std" }; - span_lint_and_sugg( cx, TRANSMUTE_BYTES_TO_STR, From a1989046c195f40f90670318c848bf843152ab74 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 15 Jan 2024 23:26:38 +0100 Subject: [PATCH 113/676] Don't emit `derive_partial_eq_without_eq` lint if the type has the `non_exhaustive` attribute --- clippy_lints/src/derive.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index d8abe411030b6..aab2550ba6eb0 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -11,8 +11,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, Ty, - TyCtxt, + self, AdtDef, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, + Ty, TyCtxt, }; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; @@ -442,6 +442,17 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { } } +fn has_non_exhaustive_attr(cx: &LateContext<'_>, adt: AdtDef<'_>) -> bool { + adt.is_variant_list_non_exhaustive() + || cx.tcx.has_attr(adt.did(), sym::non_exhaustive) + || adt.variants().iter().any(|variant_def| { + variant_def.is_field_list_non_exhaustive() || cx.tcx.has_attr(variant_def.def_id, sym::non_exhaustive) + }) + || adt + .all_fields() + .any(|field_def| cx.tcx.has_attr(field_def.did, sym::non_exhaustive)) +} + /// Implementation of the `DERIVE_PARTIAL_EQ_WITHOUT_EQ` lint. fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) { if let ty::Adt(adt, args) = ty.kind() @@ -449,6 +460,7 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq) && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) + && !has_non_exhaustive_attr(cx, *adt) && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[]) // If all of our fields implement `Eq`, we can implement `Eq` too From 136a582349a5f10ebde381cfd1eb30b03745c5c1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 15 Jan 2024 23:27:47 +0100 Subject: [PATCH 114/676] Add `non_exhaustive` checks in `derive_partial_eq_without_eq.rs` ui test --- tests/ui/derive_partial_eq_without_eq.fixed | 32 +++++++++++++++++++++ tests/ui/derive_partial_eq_without_eq.rs | 32 +++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/tests/ui/derive_partial_eq_without_eq.fixed b/tests/ui/derive_partial_eq_without_eq.fixed index a7f5d3ec7cd08..aa7a95405e02f 100644 --- a/tests/ui/derive_partial_eq_without_eq.fixed +++ b/tests/ui/derive_partial_eq_without_eq.fixed @@ -121,4 +121,36 @@ pub fn _from_mod() -> _hidden::InPubFn { #[derive(PartialEq)] struct InternalTy; +// This is a `non_exhaustive` type so should not warn. +#[derive(Debug, PartialEq)] +#[non_exhaustive] +pub struct MissingEqNonExhaustive { + foo: u32, + bar: String, +} + +// This is a `non_exhaustive` type so should not warn. +#[derive(Debug, PartialEq)] +pub struct MissingEqNonExhaustive1 { + foo: u32, + #[non_exhaustive] + bar: String, +} + +// This is a `non_exhaustive` type so should not warn. +#[derive(Debug, PartialEq)] +#[non_exhaustive] +pub enum MissingEqNonExhaustive2 { + Foo, + Bar, +} + +// This is a `non_exhaustive` type so should not warn. +#[derive(Debug, PartialEq)] +pub enum MissingEqNonExhaustive3 { + Foo, + #[non_exhaustive] + Bar, +} + fn main() {} diff --git a/tests/ui/derive_partial_eq_without_eq.rs b/tests/ui/derive_partial_eq_without_eq.rs index 476d2aee23a88..90ac7a7989e00 100644 --- a/tests/ui/derive_partial_eq_without_eq.rs +++ b/tests/ui/derive_partial_eq_without_eq.rs @@ -121,4 +121,36 @@ pub fn _from_mod() -> _hidden::InPubFn { #[derive(PartialEq)] struct InternalTy; +// This is a `non_exhaustive` type so should not warn. +#[derive(Debug, PartialEq)] +#[non_exhaustive] +pub struct MissingEqNonExhaustive { + foo: u32, + bar: String, +} + +// This is a `non_exhaustive` type so should not warn. +#[derive(Debug, PartialEq)] +pub struct MissingEqNonExhaustive1 { + foo: u32, + #[non_exhaustive] + bar: String, +} + +// This is a `non_exhaustive` type so should not warn. +#[derive(Debug, PartialEq)] +#[non_exhaustive] +pub enum MissingEqNonExhaustive2 { + Foo, + Bar, +} + +// This is a `non_exhaustive` type so should not warn. +#[derive(Debug, PartialEq)] +pub enum MissingEqNonExhaustive3 { + Foo, + #[non_exhaustive] + Bar, +} + fn main() {} From 169e2ab55b490a2b3103372b97a5d315ce8438e7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Jan 2024 12:12:28 +0100 Subject: [PATCH 115/676] Correctly handle type relative in `trait_duplication_in_bounds` lint --- clippy_lints/src/trait_bounds.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index e4054393d0ad7..768623b5d0347 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -390,6 +390,14 @@ fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &' } } +fn get_ty_res(ty: Ty<'_>) -> Option { + match ty.kind { + TyKind::Path(QPath::Resolved(_, path)) => Some(path.res), + TyKind::Path(QPath::TypeRelative(ty, _)) => get_ty_res(*ty), + _ => None, + } +} + // FIXME: ComparableTraitRef does not support nested bounds needed for associated_type_bounds fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef { ComparableTraitRef( @@ -401,10 +409,8 @@ fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef { .filter_map(|segment| { // get trait bound type arguments Some(segment.args?.args.iter().filter_map(|arg| { - if let GenericArg::Type(ty) = arg - && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind - { - return Some(path.res); + if let GenericArg::Type(ty) = arg { + return get_ty_res(**ty); } None })) From 7217c22f697db917336b1eb21bee30020c0fc97b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Jan 2024 12:13:15 +0100 Subject: [PATCH 116/676] Update `trait_duplication_in_bounds.rs` ui test to add regression for ##9961 --- tests/ui/trait_duplication_in_bounds.fixed | 31 +++++++++++++++++++++- tests/ui/trait_duplication_in_bounds.rs | 31 +++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/tests/ui/trait_duplication_in_bounds.fixed b/tests/ui/trait_duplication_in_bounds.fixed index 4fca29698e06b..7e2663d734f63 100644 --- a/tests/ui/trait_duplication_in_bounds.fixed +++ b/tests/ui/trait_duplication_in_bounds.fixed @@ -118,4 +118,33 @@ fn bad_trait_object(arg0: &(dyn Any + Send)) { unimplemented!(); } -fn main() {} +trait Proj { + type S; +} + +impl Proj for () { + type S = (); +} + +impl Proj for i32 { + type S = i32; +} + +trait Base { + fn is_base(&self); +} + +trait Derived: Base + Base<()> { + fn is_derived(&self); +} + +fn f(obj: &dyn Derived

) { + obj.is_derived(); + Base::::is_base(obj); + Base::<()>::is_base(obj); +} + +fn main() { + let _x: fn(_) = f::<()>; + let _x: fn(_) = f::; +} diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs index f67c8e35ed4cf..fede1671a4363 100644 --- a/tests/ui/trait_duplication_in_bounds.rs +++ b/tests/ui/trait_duplication_in_bounds.rs @@ -118,4 +118,33 @@ fn bad_trait_object(arg0: &(dyn Any + Send + Send)) { unimplemented!(); } -fn main() {} +trait Proj { + type S; +} + +impl Proj for () { + type S = (); +} + +impl Proj for i32 { + type S = i32; +} + +trait Base { + fn is_base(&self); +} + +trait Derived: Base + Base<()> { + fn is_derived(&self); +} + +fn f(obj: &dyn Derived

) { + obj.is_derived(); + Base::::is_base(obj); + Base::<()>::is_base(obj); +} + +fn main() { + let _x: fn(_) = f::<()>; + let _x: fn(_) = f::; +} From 06a41687b160cbb4cbf8fce0b3ad3a2e352e8338 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Thu, 14 Dec 2023 22:07:53 +0800 Subject: [PATCH 117/676] Add unstable `-Z direct-access-external-data` cmdline flag for `rustc` The new flag has been described in the Major Change Proposal at https://github.com/rust-lang/compiler-team/issues/707 --- compiler/rustc_codegen_llvm/src/mono_item.rs | 25 +++++++++++-------- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 ++ compiler/rustc_session/src/session.rs | 7 ++++++ compiler/rustc_target/src/spec/mod.rs | 11 ++++++++ .../targets/loongarch64_unknown_linux_gnu.rs | 1 + .../direct-access-external-data.md | 16 ++++++++++++ tests/codegen/direct-access-external-data.rs | 21 ++++++++++++++++ 8 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md create mode 100644 tests/codegen/direct-access-external-data.rs diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index f796ce0990f12..f763071936837 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -123,6 +123,17 @@ impl CodegenCx<'_, '_> { return false; } + // Match clang by only supporting COFF and ELF for now. + if self.tcx.sess.target.is_like_osx { + return false; + } + + // With pie relocation model calls of functions defined in the translation + // unit can use copy relocations. + if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration { + return true; + } + // Thread-local variables generally don't support copy relocations. let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval) .is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True); @@ -130,18 +141,12 @@ impl CodegenCx<'_, '_> { return false; } - // Match clang by only supporting COFF and ELF for now. - if self.tcx.sess.target.is_like_osx { - return false; + // Respect the direct-access-external-data to override default behavior if present. + if let Some(direct) = self.tcx.sess.direct_access_external_data() { + return direct; } // Static relocation model should force copy relocations everywhere. - if self.tcx.sess.relocation_model() == RelocModel::Static { - return true; - } - - // With pie relocation model calls of functions defined in the translation - // unit can use copy relocations. - self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration + self.tcx.sess.relocation_model() == RelocModel::Static } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 588139a303c52..948db6a6ea101 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -748,6 +748,7 @@ fn test_unstable_options_tracking_hash() { tracked!(debug_macros, true); tracked!(default_hidden_visibility, Some(true)); tracked!(dep_info_omit_d_target, true); + tracked!(direct_access_external_data, Some(true)); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); tracked!(emit_thin_lto, false); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c97b18ebd66ad..ff8c5f4b3568e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1553,6 +1553,8 @@ options! { dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], "in dep-info output, omit targets for tracking dependencies of the dep-info files \ themselves (default: no)"), + direct_access_external_data: Option = (None, parse_opt_bool, [TRACKED], + "Direct or use GOT indirect to reference external data symbols"), dual_proc_macros: bool = (false, parse_bool, [TRACKED], "load proc macros for both target and host, but only link to the target (default: no)"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 720599f609544..392485e2238c5 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -793,6 +793,13 @@ impl Session { self.opts.unstable_opts.tls_model.unwrap_or(self.target.tls_model) } + pub fn direct_access_external_data(&self) -> Option { + self.opts + .unstable_opts + .direct_access_external_data + .or(self.target.direct_access_external_data) + } + pub fn split_debuginfo(&self) -> SplitDebuginfo { self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo) } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8e26327196a1a..7979be7b5d6e8 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1885,6 +1885,8 @@ pub struct TargetOptions { /// passed, and cannot be disabled even via `-C`. Corresponds to `llc /// -mattr=$features`. pub features: StaticCow, + /// Direct or use GOT indirect to reference external data symbols + pub direct_access_external_data: Option, /// Whether dynamic linking is available on this target. Defaults to false. pub dynamic_linking: bool, /// Whether dynamic linking can export TLS globals. Defaults to true. @@ -2279,6 +2281,7 @@ impl Default for TargetOptions { asm_args: cvs![], cpu: "generic".into(), features: "".into(), + direct_access_external_data: None, dynamic_linking: false, dll_tls_export: true, only_cdylib: false, @@ -2575,6 +2578,12 @@ impl Target { base.$key_name = s as u32; } } ); + ($key_name:ident, Option) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { + base.$key_name = Some(s); + } + } ); ($key_name:ident, Option) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { @@ -3003,6 +3012,7 @@ impl Target { key!(cpu); key!(features); key!(dynamic_linking, bool); + key!(direct_access_external_data, Option); key!(dll_tls_export, bool); key!(only_cdylib, bool); key!(executables, bool); @@ -3257,6 +3267,7 @@ impl ToJson for Target { target_option_val!(cpu); target_option_val!(features); target_option_val!(dynamic_linking); + target_option_val!(direct_access_external_data); target_option_val!(dll_tls_export); target_option_val!(only_cdylib); target_option_val!(executables); 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..234270c999b2a 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 @@ -11,6 +11,7 @@ pub fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + direct_access_external_data: Some(false), ..base::linux_gnu::opts() }, } diff --git a/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md b/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md new file mode 100644 index 0000000000000..c72df43796038 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md @@ -0,0 +1,16 @@ +# `direct_access_external_data` + +The tracking issue for this feature is: https://github.com/rust-lang/compiler-team/issues/707 + +------------------------ + +Option `-Z direct-access-external-data` controls how to access symbols of +external data. + +Supported values for this option are: + +- `yes` - Don't use GOT indirection to reference external data symbols. +- `no` - Use GOT indirection to reference external data symbols. + +If the option is not explicitly specified, different targets have different +default values. diff --git a/tests/codegen/direct-access-external-data.rs b/tests/codegen/direct-access-external-data.rs new file mode 100644 index 0000000000000..ec4bfc33518db --- /dev/null +++ b/tests/codegen/direct-access-external-data.rs @@ -0,0 +1,21 @@ +// only-loongarch64-unknown-linux-gnu + +// revisions: DEFAULT DIRECT INDIRECT +// [DEFAULT] compile-flags: -C relocation-model=static +// [DIRECT] compile-flags: -C relocation-model=static -Z direct-access-external-data=yes +// [INDIRECT] compile-flags: -C relocation-model=static -Z direct-access-external-data=no + +#![crate_type = "rlib"] + +// DEFAULT: @VAR = external {{.*}} global i32 +// DIRECT: @VAR = external dso_local {{.*}} global i32 +// INDIRECT: @VAR = external {{.*}} global i32 + +extern "C" { + static VAR: i32; +} + +#[no_mangle] +pub fn get() -> i32 { + unsafe { VAR } +} From 1696148a894f6e5fd8857400ebede44dedee0e2c Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 16 Jan 2024 10:19:23 -0500 Subject: [PATCH 118/676] Merge into larger interval set This reduces the work done while merging rows. In at least one case (issue 50450), we have thousands of union([range], [20,000 ranges]), which previously inserted each of the 20,000 ranges one by one. Now we only insert one range into the right hand set after copying the set over. --- compiler/rustc_index/src/interval.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index d3cf267dc9d79..0c1180b3e9800 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -236,6 +236,12 @@ impl IntervalSet { I: Step, { assert_eq!(self.domain, other.domain); + if self.map.len() < other.map.len() { + let backup = self.clone(); + self.map.clone_from(&other.map); + return self.union(&backup); + } + let mut did_insert = false; for range in other.iter_intervals() { did_insert |= self.insert_range(range); From f7376a0f8cc4177955e01d88e56aabbfd635a566 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 15 Jan 2024 19:38:53 +0000 Subject: [PATCH 119/676] Deal with additional wrapping of async closure body in clippy --- clippy_lints/src/async_yields_async.rs | 98 +++++++++++++--------- clippy_lints/src/redundant_closure_call.rs | 20 ++++- tests/ui/author/blocks.stdout | 6 +- 3 files changed, 82 insertions(+), 42 deletions(-) diff --git a/clippy_lints/src/async_yields_async.rs b/clippy_lints/src/async_yields_async.rs index bb08ac7508bc2..eeaa3de3725fb 100644 --- a/clippy_lints/src/async_yields_async.rs +++ b/clippy_lints/src/async_yields_async.rs @@ -45,50 +45,72 @@ declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]); impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - // For functions, with explicitly defined types, don't warn. - // XXXkhuey maybe we should? - if let ExprKind::Closure(Closure { - kind: - ClosureKind::Coroutine(CoroutineKind::Desugared( - CoroutineDesugaring::Async, - CoroutineSource::Block | CoroutineSource::Closure, - )), + let ExprKind::Closure(Closure { + kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, kind)), body: body_id, .. }) = expr.kind - { - if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() { - let typeck_results = cx.tcx.typeck_body(*body_id); - let body = cx.tcx.hir().body(*body_id); - let expr_ty = typeck_results.expr_ty(body.value); + else { + return; + }; - if implements_trait(cx, expr_ty, future_trait_def_id, &[]) { - let return_expr_span = match &body.value.kind { - // XXXkhuey there has to be a better way. - ExprKind::Block(block, _) => block.expr.map(|e| e.span), - ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span), - _ => None, - }; - if let Some(return_expr_span) = return_expr_span { - span_lint_hir_and_then( - cx, - ASYNC_YIELDS_ASYNC, - body.value.hir_id, + let body_expr = match kind { + CoroutineSource::Fn => { + // For functions, with explicitly defined types, don't warn. + // XXXkhuey maybe we should? + return; + }, + CoroutineSource::Block => cx.tcx.hir().body(*body_id).value, + CoroutineSource::Closure => { + // Like `async fn`, async closures are wrapped in an additional block + // to move all of the closure's arguments into the future. + + let async_closure_body = cx.tcx.hir().body(*body_id).value; + let ExprKind::Block(block, _) = async_closure_body.kind else { + return; + }; + let Some(block_expr) = block.expr else { + return; + }; + let ExprKind::DropTemps(body_expr) = block_expr.kind else { + return; + }; + body_expr + }, + }; + + let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() else { + return; + }; + + let typeck_results = cx.tcx.typeck_body(*body_id); + let expr_ty = typeck_results.expr_ty(body_expr); + + if implements_trait(cx, expr_ty, future_trait_def_id, &[]) { + let return_expr_span = match &body_expr.kind { + // XXXkhuey there has to be a better way. + ExprKind::Block(block, _) => block.expr.map(|e| e.span), + ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span), + _ => None, + }; + if let Some(return_expr_span) = return_expr_span { + span_lint_hir_and_then( + cx, + ASYNC_YIELDS_ASYNC, + body_expr.hir_id, + return_expr_span, + "an async construct yields a type which is itself awaitable", + |db| { + db.span_label(body_expr.span, "outer async construct"); + db.span_label(return_expr_span, "awaitable value not awaited"); + db.span_suggestion( return_expr_span, - "an async construct yields a type which is itself awaitable", - |db| { - db.span_label(body.value.span, "outer async construct"); - db.span_label(return_expr_span, "awaitable value not awaited"); - db.span_suggestion( - return_expr_span, - "consider awaiting this value", - format!("{}.await", snippet(cx, return_expr_span, "..")), - Applicability::MaybeIncorrect, - ); - }, + "consider awaiting this value", + format!("{}.await", snippet(cx, return_expr_span, "..")), + Applicability::MaybeIncorrect, ); - } - } + }, + ); } } } diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index cde08dfcc748d..334e6770ae407 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -5,7 +5,9 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; -use rustc_hir::{intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Node}; +use rustc_hir::{ + intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; @@ -166,10 +168,22 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { if coroutine_kind.is_async() && let hir::ExprKind::Closure(closure) = body.kind { - let async_closure_body = cx.tcx.hir().body(closure.body); + // Like `async fn`, async closures are wrapped in an additional block + // to move all of the closure's arguments into the future. + + let async_closure_body = cx.tcx.hir().body(closure.body).value; + let ExprKind::Block(block, _) = async_closure_body.kind else { + return; + }; + let Some(block_expr) = block.expr else { + return; + }; + let ExprKind::DropTemps(body_expr) = block_expr.kind else { + return; + }; // `async x` is a syntax error, so it becomes `async { x }` - if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) { + if !matches!(body_expr.kind, hir::ExprKind::Block(_, _)) { hint = hint.blockify(); } diff --git a/tests/ui/author/blocks.stdout b/tests/ui/author/blocks.stdout index 62de661f8ff86..8c4d71e68f80f 100644 --- a/tests/ui/author/blocks.stdout +++ b/tests/ui/author/blocks.stdout @@ -48,7 +48,11 @@ if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_ && expr2 = &cx.tcx.hir().body(body_id1).value && let ExprKind::Block(block, None) = expr2.kind && block.stmts.is_empty() - && block.expr.is_none() + && let Some(trailing_expr) = block.expr + && let ExprKind::DropTemps(expr3) = trailing_expr.kind + && let ExprKind::Block(block1, None) = expr3.kind + && block1.stmts.is_empty() + && block1.expr.is_none() { // report your lint here } From bc3fb5245a248070b76e535be4f342e2be12a9b5 Mon Sep 17 00:00:00 2001 From: LegionMammal978 Date: Tue, 16 Jan 2024 14:58:42 -0500 Subject: [PATCH 120/676] Rename `pointer` field on `Pin` The internal, unstable field of `Pin` can conflict with fields from the inner type accessed via the `Deref` impl. Rename it from `pointer` to `__pointer`, to make it less likely to conflict with anything else. --- .../src/fn_ctxt/suggestions.rs | 2 +- library/core/src/pin.rs | 46 +++++++++++-------- src/etc/natvis/libcore.natvis | 4 +- ...ine_coroutine.main.Inline.panic-abort.diff | 2 +- ...ne_coroutine.main.Inline.panic-unwind.diff | 2 +- .../feature-gate-unsafe_pin_internals.rs | 2 +- tests/ui/pin-macro/cant_access_internals.rs | 2 +- .../ui/pin-macro/cant_access_internals.stderr | 4 +- 8 files changed, 35 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 81b7de7f63497..83c544a9605bd 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2038,7 +2038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let field_is_local = sole_field.did.is_local(); let field_is_accessible = sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx) - // Skip suggestions for unstable public fields (for example `Pin::pointer`) + // Skip suggestions for unstable public fields (for example `Pin::__pointer`) && matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked); if !field_is_local && !field_is_accessible { diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index bb6c81a486a59..a0227d9130bb7 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1092,14 +1092,20 @@ pub struct Pin { // - deter downstream users from accessing it (which would be unsound!), // - let the `pin!` macro access it (such a macro requires using struct // literal syntax in order to benefit from lifetime extension). - // Long-term, `unsafe` fields or macro hygiene are expected to offer more robust alternatives. + // + // However, if the `Deref` impl exposes a field with the same name as this + // field, then the two will collide, resulting in a confusing error when the + // user attempts to access the field through a `Pin`. Therefore, the + // name `__pointer` is designed to be unlikely to collide with any other + // field. Long-term, macro hygiene is expected to offer a more robust + // alternative, alongside `unsafe` fields. #[unstable(feature = "unsafe_pin_internals", issue = "none")] #[doc(hidden)] - pub pointer: Ptr, + pub __pointer: Ptr, } // The following implementations aren't derived in order to avoid soundness -// issues. `&self.pointer` should not be accessible to untrusted trait +// issues. `&self.__pointer` should not be accessible to untrusted trait // implementations. // // See for more details. @@ -1212,7 +1218,7 @@ impl> Pin { #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const fn into_inner(pin: Pin) -> Ptr { - pin.pointer + pin.__pointer } } @@ -1349,7 +1355,7 @@ impl Pin { #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin", since = "1.33.0")] pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin { - Pin { pointer } + Pin { __pointer: pointer } } /// Gets a shared reference to the pinned value this [`Pin`] points to. @@ -1363,7 +1369,7 @@ impl Pin { #[inline(always)] pub fn as_ref(&self) -> Pin<&Ptr::Target> { // SAFETY: see documentation on this function - unsafe { Pin::new_unchecked(&*self.pointer) } + unsafe { Pin::new_unchecked(&*self.__pointer) } } /// Unwraps this `Pin`, returning the underlying `Ptr`. @@ -1388,7 +1394,7 @@ impl Pin { #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { - pin.pointer + pin.__pointer } } @@ -1426,7 +1432,7 @@ impl Pin { #[inline(always)] pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> { // SAFETY: see documentation on this function - unsafe { Pin::new_unchecked(&mut *self.pointer) } + unsafe { Pin::new_unchecked(&mut *self.__pointer) } } /// Assigns a new value to the memory location pointed to by the `Pin`. @@ -1455,7 +1461,7 @@ impl Pin { where Ptr::Target: Sized, { - *(self.pointer) = value; + *(self.__pointer) = value; } } @@ -1481,7 +1487,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { U: ?Sized, F: FnOnce(&T) -> &U, { - let pointer = &*self.pointer; + let pointer = &*self.__pointer; let new_pointer = func(pointer); // SAFETY: the safety contract for `new_unchecked` must be @@ -1511,7 +1517,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin", since = "1.33.0")] pub const fn get_ref(self) -> &'a T { - self.pointer + self.__pointer } } @@ -1522,7 +1528,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin", since = "1.33.0")] pub const fn into_ref(self) -> Pin<&'a T> { - Pin { pointer: self.pointer } + Pin { __pointer: self.__pointer } } /// Gets a mutable reference to the data inside of this `Pin`. @@ -1542,7 +1548,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { where T: Unpin, { - self.pointer + self.__pointer } /// Gets a mutable reference to the data inside of this `Pin`. @@ -1560,7 +1566,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] pub const unsafe fn get_unchecked_mut(self) -> &'a mut T { - self.pointer + self.__pointer } /// Construct a new pin by mapping the interior value. @@ -1684,21 +1690,21 @@ impl Receiver for Pin {} #[stable(feature = "pin", since = "1.33.0")] impl fmt::Debug for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.pointer, f) + fmt::Debug::fmt(&self.__pointer, f) } } #[stable(feature = "pin", since = "1.33.0")] impl fmt::Display for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.pointer, f) + fmt::Display::fmt(&self.__pointer, f) } } #[stable(feature = "pin", since = "1.33.0")] impl fmt::Pointer for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&self.pointer, f) + fmt::Pointer::fmt(&self.__pointer, f) } } @@ -1941,16 +1947,16 @@ pub macro pin($value:expr $(,)?) { // instead, dropped _at the end of the enscoping block_. // For instance, // ```rust - // let p = Pin { pointer: &mut }; + // let p = Pin { __pointer: &mut }; // ``` // becomes: // ```rust // let mut anon = ; - // let p = Pin { pointer: &mut anon }; + // let p = Pin { __pointer: &mut anon }; // ``` // which is *exactly* what we want. // // See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension // for more info. - $crate::pin::Pin::<&mut _> { pointer: &mut { $value } } + $crate::pin::Pin::<&mut _> { __pointer: &mut { $value } } } diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 624d8cc5cc55a..f8569ef2594b4 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -99,9 +99,9 @@ - Pin({(void*)pointer}: {pointer}) + Pin({(void*)__pointer}: {__pointer}) - pointer + __pointer diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 8e53427e7e060..a38b8246bdef2 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -36,7 +36,7 @@ - _4 = g() -> [return: bb1, unwind unreachable]; + _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index b06db41af9d40..dc6628ab44c5f 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ - _4 = g() -> [return: bb1, unwind continue]; + _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs index 134ea25b75afb..594a2672d435d 100644 --- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs +++ b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs @@ -7,7 +7,7 @@ use core::{marker::PhantomPinned, pin::Pin}; /// The `unsafe_pin_internals` is indeed unsound. fn non_unsafe_pin_new_unchecked(pointer: &mut T) -> Pin<&mut T> { - Pin { pointer } + Pin { __pointer: pointer } } fn main() { diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs index 5826a18b5718b..4aeb6a643d959 100644 --- a/tests/ui/pin-macro/cant_access_internals.rs +++ b/tests/ui/pin-macro/cant_access_internals.rs @@ -8,5 +8,5 @@ use core::{ fn main() { let mut phantom_pinned = pin!(PhantomPinned); - mem::take(phantom_pinned.pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals' + mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals' } diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr index 2737b84f5995b..444314a9d8bb3 100644 --- a/tests/ui/pin-macro/cant_access_internals.stderr +++ b/tests/ui/pin-macro/cant_access_internals.stderr @@ -1,8 +1,8 @@ error[E0658]: use of unstable library feature 'unsafe_pin_internals' --> $DIR/cant_access_internals.rs:11:15 | -LL | mem::take(phantom_pinned.pointer); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | mem::take(phantom_pinned.__pointer); + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(unsafe_pin_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date From 33e1e6f783cb3a725f2ff0f134400031890d6f7f Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Wed, 17 Jan 2024 03:14:16 +0100 Subject: [PATCH 121/676] Add `PatKind::Err` --- clippy_lints/src/equatable_if_let.rs | 3 ++- clippy_lints/src/matches/match_same_arms.rs | 5 ++++- clippy_lints/src/unnested_or_patterns.rs | 2 +- clippy_lints/src/utils/author.rs | 1 + clippy_utils/src/hir_utils.rs | 2 +- clippy_utils/src/lib.rs | 1 + 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index 3c43529425265..4e728d61b853a 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -51,7 +51,8 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { | PatKind::Binding(..) | PatKind::Wild | PatKind::Never - | PatKind::Or(_) => false, + | PatKind::Or(_) + | PatKind::Err(_) => false, PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x), diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index c823d07e2bd3d..5ca161e93096d 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -11,7 +11,7 @@ use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, P use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::Symbol; +use rustc_span::{ErrorGuaranteed, Symbol}; use super::MATCH_SAME_ARMS; @@ -167,6 +167,8 @@ enum NormalizedPat<'a> { /// contains everything afterwards. Note that either side, or both sides, may contain zero /// patterns. Slice(&'a [Self], Option<&'a [Self]>), + /// A placeholder for a pattern that wasn't well formed in some way. + Err(ErrorGuaranteed), } #[derive(Clone, Copy)] @@ -329,6 +331,7 @@ impl<'a> NormalizedPat<'a> { arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))), wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))), ), + PatKind::Err(guar) => Self::Err(guar), } } diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 77adcdd0e6bfb..7246214f9bf87 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -226,7 +226,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, // which we would want to join with other `C(p_j)`s. - Ident(.., None) | Lit(_) | Wild | Never | Path(..) | Range(..) | Rest | MacCall(_) + Ident(.., None) | Lit(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_) // Skip immutable refs, as grouping them saves few characters, // and almost always requires adding parens (increasing noisiness). // In the case of only two patterns, replacement adds net characters. diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 8d38b87e1d794..b26ebe5cee321 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -710,6 +710,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.slice(start, |pat| self.pat(pat)); self.slice(end, |pat| self.pat(pat)); }, + PatKind::Err(_) => kind!("Err"), } } diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 482eaed77d1d3..979b117db256a 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -1007,7 +1007,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } e.hash(&mut self.s); }, - PatKind::Never | PatKind::Wild => {}, + PatKind::Never | PatKind::Wild | PatKind::Err(_) => {}, } } diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index cdf8528f48a27..2e54690d123cc 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1733,6 +1733,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { }, } }, + PatKind::Err(_) => true, } } From 4488653ec6e4591ebfc43470cd3718f1f2c4fce2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 16:58:29 +0000 Subject: [PATCH 122/676] Fix clippy --- clippy_lints/src/derive.rs | 3 ++- clippy_lints/src/inherent_impl.rs | 3 ++- clippy_lints/src/iter_without_into_iter.rs | 2 +- clippy_lints/src/len_zero.rs | 5 +++-- clippy_lints/src/methods/or_fun_call.rs | 3 ++- clippy_utils/src/lib.rs | 8 +++++--- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index d8abe411030b6..d1fe9f5cbece7 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -386,7 +386,8 @@ fn check_unsafe_derive_deserialize<'tcx>( && cx .tcx .inherent_impls(def.did()) - .iter() + .into_iter() + .flatten() .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local())) .any(|imp| has_unsafe(cx, imp)) { diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index e4781752e757b..fb7b82ec304ef 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -53,9 +53,10 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { // List of spans to lint. (lint_span, first_span) let mut lint_spans = Vec::new(); + let Ok(impls) = cx.tcx.crate_inherent_impls(()) else { return }; let inherent_impls = cx .tcx - .with_stable_hashing_context(|hcx| cx.tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true)); + .with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true)); for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| { impls.len() > 1 diff --git a/clippy_lints/src/iter_without_into_iter.rs b/clippy_lints/src/iter_without_into_iter.rs index 903d3a2ab8960..82a37bb4f278a 100644 --- a/clippy_lints/src/iter_without_into_iter.rs +++ b/clippy_lints/src/iter_without_into_iter.rs @@ -139,7 +139,7 @@ fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iter fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool { if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) { - cx.tcx.inherent_impls(ty_did).iter().any(|&did| { + cx.tcx.inherent_impls(ty_did).into_iter().flatten().any(|&did| { cx.tcx .associated_items(did) .filter_by_name_unhygienic(method_name) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index c09d3d1862b0c..c1ab020117ca6 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -441,7 +441,8 @@ fn check_for_is_empty( let is_empty = cx .tcx .inherent_impls(impl_ty) - .iter() + .into_iter() + .flatten() .flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty)) .find(|item| item.kind == AssocKind::Fn); @@ -605,7 +606,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Checks the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool { let is_empty = sym!(is_empty); - cx.tcx.inherent_impls(id).iter().any(|imp| { + cx.tcx.inherent_impls(id).into_iter().flatten().any(|imp| { cx.tcx .associated_items(*imp) .filter_by_name_unhygienic(is_empty) diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index e38c66f6741d2..0602eeaa70417 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -73,7 +73,8 @@ pub(super) fn check<'tcx>( let has_suggested_method = receiver_ty.ty_adt_def().is_some_and(|adt_def| { cx.tcx .inherent_impls(adt_def.did()) - .iter() + .into_iter() + .flatten() .flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg)) .any(|assoc| { assoc.fn_has_self_parameter diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index cdf8528f48a27..1a4b22799f2ab 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -534,10 +534,11 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator SimplifiedType::Uint(UintTy::U128), "f32" => SimplifiedType::Float(FloatTy::F32), "f64" => SimplifiedType::Float(FloatTy::F64), - _ => return [].iter().copied(), + #[allow(trivial_casts)] + _ => return Result::<_, rustc_errors::ErrorGuaranteed>::Ok(&[] as &[_]).into_iter().flatten().copied(), }; - tcx.incoherent_impls(ty).iter().copied() + tcx.incoherent_impls(ty).into_iter().flatten().copied() } fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec { @@ -663,7 +664,8 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec { // `impl S { ... }` let inherent_impl_children = tcx .inherent_impls(def_id) - .iter() + .into_iter() + .flatten() .flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment)); let direct_children = item_children_by_name(tcx, def_id, segment); From 6231ca5f5eddc7691a79373804e9530e19df9a5d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 18 Jan 2024 06:50:06 +0000 Subject: [PATCH 123/676] 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 9fe7c6a7ec4ff03300c69046e2055b6619956864 Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Thu, 18 Jan 2024 17:56:35 +0800 Subject: [PATCH 124/676] finally came up with some repro code --- tests/ui/auxiliary/proc_macro_attr.rs | 34 +++++++++++++++++-- tests/ui/semicolon_if_nothing_returned.fixed | 27 +++++++++++++++ tests/ui/semicolon_if_nothing_returned.rs | 27 +++++++++++++++ tests/ui/semicolon_if_nothing_returned.stderr | 24 +++++++++---- 4 files changed, 104 insertions(+), 8 deletions(-) diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs index c58795575160b..ac544737099c6 100644 --- a/tests/ui/auxiliary/proc_macro_attr.rs +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -11,8 +11,8 @@ use quote::{quote, quote_spanned}; use syn::spanned::Spanned; use syn::token::Star; use syn::{ - parse_macro_input, parse_quote, FnArg, ImplItem, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, - TraitItem, Type, + parse_macro_input, parse_quote, FnArg, ImplItem, ItemFn, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, + Signature, TraitItem, Type, }; #[proc_macro_attribute] @@ -95,3 +95,33 @@ pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStrea TokenStream::from(quote!(#item)) } + +#[proc_macro_attribute] +pub fn fake_main(_attr: TokenStream, item: TokenStream) -> TokenStream { + let mut item = parse_macro_input!(item as ItemFn); + let span = item.block.brace_token.span; + + if item.sig.asyncness.is_some() { + item.sig.asyncness = None; + } + + let crate_name = quote! { fake_crate }; + let block = item.block; + item.block = syn::parse_quote_spanned! { + span => + { + #crate_name::block_on(async { + #block + }) + } + }; + + quote! { + mod #crate_name { + pub fn block_on(_fut: F) {} + } + + #item + } + .into() +} diff --git a/tests/ui/semicolon_if_nothing_returned.fixed b/tests/ui/semicolon_if_nothing_returned.fixed index bbcc0de27d115..bc96b959fc543 100644 --- a/tests/ui/semicolon_if_nothing_returned.fixed +++ b/tests/ui/semicolon_if_nothing_returned.fixed @@ -1,6 +1,11 @@ +//@aux-build:proc_macro_attr.rs + #![warn(clippy::semicolon_if_nothing_returned)] #![allow(clippy::redundant_closure, clippy::uninlined_format_args, clippy::needless_late_init)] +#[macro_use] +extern crate proc_macro_attr; + fn get_unit() {} // the functions below trigger the lint @@ -120,3 +125,25 @@ fn let_else_stmts() { return; }; } + +mod issue12123 { + #[rustfmt::skip] + mod this_triggers { + #[fake_main]; + async fn main() { + + } + } + + mod and_this { + #[fake_main]; + async fn main() { + println!("hello"); + } + } + + mod but_this_does_not { + #[fake_main] + async fn main() {} + } +} diff --git a/tests/ui/semicolon_if_nothing_returned.rs b/tests/ui/semicolon_if_nothing_returned.rs index fdc9c0c33f5a3..e5713ce062bc0 100644 --- a/tests/ui/semicolon_if_nothing_returned.rs +++ b/tests/ui/semicolon_if_nothing_returned.rs @@ -1,6 +1,11 @@ +//@aux-build:proc_macro_attr.rs + #![warn(clippy::semicolon_if_nothing_returned)] #![allow(clippy::redundant_closure, clippy::uninlined_format_args, clippy::needless_late_init)] +#[macro_use] +extern crate proc_macro_attr; + fn get_unit() {} // the functions below trigger the lint @@ -120,3 +125,25 @@ fn let_else_stmts() { return; }; } + +mod issue12123 { + #[rustfmt::skip] + mod this_triggers { + #[fake_main] + async fn main() { + + } + } + + mod and_this { + #[fake_main] + async fn main() { + println!("hello"); + } + } + + mod but_this_does_not { + #[fake_main] + async fn main() {} + } +} diff --git a/tests/ui/semicolon_if_nothing_returned.stderr b/tests/ui/semicolon_if_nothing_returned.stderr index 66373a13c5690..0d5381ef6212a 100644 --- a/tests/ui/semicolon_if_nothing_returned.stderr +++ b/tests/ui/semicolon_if_nothing_returned.stderr @@ -1,5 +1,5 @@ error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:8:5 + --> $DIR/semicolon_if_nothing_returned.rs:13:5 | LL | println!("Hello") | ^^^^^^^^^^^^^^^^^ help: add a `;` here: `println!("Hello");` @@ -8,28 +8,40 @@ LL | println!("Hello") = help: to override `-D warnings` add `#[allow(clippy::semicolon_if_nothing_returned)]` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:12:5 + --> $DIR/semicolon_if_nothing_returned.rs:17:5 | LL | get_unit() | ^^^^^^^^^^ help: add a `;` here: `get_unit();` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:17:5 + --> $DIR/semicolon_if_nothing_returned.rs:22:5 | LL | y = x + 1 | ^^^^^^^^^ help: add a `;` here: `y = x + 1;` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:23:9 + --> $DIR/semicolon_if_nothing_returned.rs:28:9 | LL | hello() | ^^^^^^^ help: add a `;` here: `hello();` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:34:9 + --> $DIR/semicolon_if_nothing_returned.rs:39:9 | LL | ptr::drop_in_place(s.as_mut_ptr()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());` -error: aborting due to 5 previous errors +error: consider adding a `;` to the last statement for consistent formatting + --> $DIR/semicolon_if_nothing_returned.rs:132:9 + | +LL | #[fake_main] + | ^^^^^^^^^^^^ help: add a `;` here: `#[fake_main];` + +error: consider adding a `;` to the last statement for consistent formatting + --> $DIR/semicolon_if_nothing_returned.rs:139:9 + | +LL | #[fake_main] + | ^^^^^^^^^^^^ help: add a `;` here: `#[fake_main];` + +error: aborting due to 7 previous errors From 46652dd254bc9c413d14cec637c7f21ac6601e05 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 17 Jan 2024 14:26:26 +0000 Subject: [PATCH 125/676] llvm: simplify data layout check Don't skip the inconsistent data layout check for custom LLVMs. With #118708, all targets will have a simple test that would trigger this check if LLVM's data layouts do change - so data layouts would be corrected during the LLVM upgrade. Therefore, with builtin targets, this check won't trigger with our LLVM because each target will have been confirmed to work. With non-builtin targets, this check is probably useful to have because you can change the data layout in your target and if its wrong then that could lead to bugs. When using a custom LLVM, the same justification makes sense for non-builtin targets as with our LLVM, the user can update their target to match their LLVM and that's probably a good thing to do. However, with a custom LLVM, the user cannot change the builtin target data layouts if they don't match - though given that the compiler's data layout is used for layout computation and a bunch of other things - you could get some bugs because of the mismatch and probably want to know about that. `CFG_LLVM_ROOT` was also always set during local development with `download-ci-llvm` so this bug would never trigger locally. Signed-off-by: David Wood --- compiler/rustc_codegen_llvm/messages.ftl | 3 ++ compiler/rustc_codegen_llvm/src/context.rs | 38 +++++-------------- compiler/rustc_codegen_llvm/src/errors.rs | 9 +++++ src/bootstrap/src/core/build_steps/compile.rs | 5 --- src/tools/tidy/src/ui_tests.rs | 7 ++-- tests/run-make/target-specs/Makefile | 2 +- tests/ui/codegen/mismatched-data-layout.json | 13 +++++++ tests/ui/codegen/mismatched-data-layouts.rs | 14 +++++++ .../ui/codegen/mismatched-data-layouts.stderr | 4 ++ 9 files changed, 57 insertions(+), 38 deletions(-) create mode 100644 tests/ui/codegen/mismatched-data-layout.json create mode 100644 tests/ui/codegen/mismatched-data-layouts.rs create mode 100644 tests/ui/codegen/mismatched-data-layouts.stderr diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index 7a86ddc7556a0..d5bc04f594da1 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -39,6 +39,9 @@ codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdy codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type without `-Zdylib-lto` +codegen_llvm_mismatch_data_layout = + data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}` + codegen_llvm_missing_features = add the missing features in a `target_feature` attribute diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1d1b6e6148dd2..b0f0b650e77f3 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -34,6 +34,7 @@ use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel}; use smallvec::SmallVec; use libc::c_uint; +use std::borrow::Borrow; use std::cell::{Cell, RefCell}; use std::ffi::CStr; use std::str; @@ -147,8 +148,7 @@ pub unsafe fn create_module<'ll>( } // Ensure the data-layout values hardcoded remain the defaults. - if sess.target.is_builtin { - // tm is disposed by its drop impl + { let tm = crate::back::write::create_informational_target_machine(tcx.sess); llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm); @@ -156,33 +156,13 @@ pub unsafe fn create_module<'ll>( let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes()) .expect("got a non-UTF8 data-layout from LLVM"); - // Unfortunately LLVM target specs change over time, and right now we - // don't have proper support to work with any more than one - // `data_layout` than the one that is in the rust-lang/rust repo. If - // this compiler is configured against a custom LLVM, we may have a - // differing data layout, even though we should update our own to use - // that one. - // - // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we - // disable this check entirely as we may be configured with something - // that has a different target layout. - // - // Unsure if this will actually cause breakage when rustc is configured - // as such. - // - // FIXME(#34960) - let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or(""); - let custom_llvm_used = !cfg_llvm_root.trim().is_empty(); - - if !custom_llvm_used && target_data_layout != llvm_data_layout { - bug!( - "data-layout for target `{rustc_target}`, `{rustc_layout}`, \ - differs from LLVM target's `{llvm_target}` default layout, `{llvm_layout}`", - rustc_target = sess.opts.target_triple, - rustc_layout = target_data_layout, - llvm_target = sess.target.llvm_target, - llvm_layout = llvm_data_layout - ); + if target_data_layout != llvm_data_layout { + tcx.dcx().emit_err(crate::errors::MismatchedDataLayout { + rustc_target: sess.opts.target_triple.to_string().as_str(), + rustc_layout: target_data_layout.as_str(), + llvm_target: sess.target.llvm_target.borrow(), + llvm_layout: llvm_data_layout, + }); } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 697ce6022984b..d82ff6656f4d3 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -244,3 +244,12 @@ pub(crate) struct CopyBitcode { pub struct UnknownCompression { pub algorithm: &'static str, } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_mismatch_data_layout)] +pub struct MismatchedDataLayout<'a> { + pub rustc_target: &'a str, + pub rustc_layout: &'a str, + pub llvm_target: &'a str, + pub llvm_layout: &'a str, +} diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 190f0fe3cddcf..663ec6fe08645 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1103,16 +1103,11 @@ pub fn rustc_cargo_env( /// Pass down configuration from the LLVM build into the build of /// rustc_llvm and rustc_codegen_llvm. fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) { - let target_config = builder.config.target_config.get(&target); - if builder.is_rust_llvm(target) { cargo.env("LLVM_RUSTLLVM", "1"); } let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target }); cargo.env("LLVM_CONFIG", &llvm_config); - if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - cargo.env("CFG_LLVM_ROOT", s); - } // Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script // expects these to be passed via the `LLVM_LINKER_FLAGS` env variable, separated by diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 95cf9f8cb13ad..85553d2e3384a 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -24,9 +24,10 @@ const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint - "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs - "tests/ui/commandline-argfile-badutf8.args", // passing args via a file - "tests/ui/commandline-argfile.args", // passing args via a file + "tests/ui/codegen/mismatched-data-layout.json", // testing mismatched data layout w/ custom targets + "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs + "tests/ui/commandline-argfile-badutf8.args", // passing args via a file + "tests/ui/commandline-argfile.args", // passing args via a file "tests/ui/crate-loading/auxiliary/libfoo.rlib", // testing loading a manually created rlib "tests/ui/include-macros/data.bin", // testing including data with the include macros "tests/ui/include-macros/file.txt", // testing including data with the include macros diff --git a/tests/run-make/target-specs/Makefile b/tests/run-make/target-specs/Makefile index 62d5365a73d03..161b66021857b 100644 --- a/tests/run-make/target-specs/Makefile +++ b/tests/run-make/target-specs/Makefile @@ -9,4 +9,4 @@ all: $(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json - $(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin' $(RUSTC) foo.rs --target=endianness-mismatch 2>&1 | $(CGREP) '"data-layout" claims architecture is little-endian' - $(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib + $(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib 2>&1 | $(CGREP) 'data-layout for target' diff --git a/tests/ui/codegen/mismatched-data-layout.json b/tests/ui/codegen/mismatched-data-layout.json new file mode 100644 index 0000000000000..4cb0602dc75b5 --- /dev/null +++ b/tests/ui/codegen/mismatched-data-layout.json @@ -0,0 +1,13 @@ +{ + "llvm-target": "x86_64-unknown-none-gnu", + "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", + "arch": "x86_64", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "os": "unknown", + "linker-flavor": "ld.lld", + "linker": "rust-lld", + "executables": true +} + diff --git a/tests/ui/codegen/mismatched-data-layouts.rs b/tests/ui/codegen/mismatched-data-layouts.rs new file mode 100644 index 0000000000000..047ec155fdca6 --- /dev/null +++ b/tests/ui/codegen/mismatched-data-layouts.rs @@ -0,0 +1,14 @@ +// This test checks that data layout mismatches emit an error. +// +// build-fail +// needs-llvm-components: x86 +// compile-flags: --crate-type=lib --target={{src-base}}/codegen/mismatched-data-layout.json -Z unstable-options +// error-pattern: differs from LLVM target's +// normalize-stderr-test: "`, `[A-Za-z0-9-:]*`" -> "`, `normalized data layout`" +// normalize-stderr-test: "layout, `[A-Za-z0-9-:]*`" -> "layout, `normalized data layout`" + +#![feature(lang_items, no_core, auto_traits)] +#![no_core] + +#[lang = "sized"] +trait Sized {} diff --git a/tests/ui/codegen/mismatched-data-layouts.stderr b/tests/ui/codegen/mismatched-data-layouts.stderr new file mode 100644 index 0000000000000..1fe242266dff7 --- /dev/null +++ b/tests/ui/codegen/mismatched-data-layouts.stderr @@ -0,0 +1,4 @@ +error: data-layout for target `mismatched-data-layout-7814813422914914169`, `normalized data layout`, differs from LLVM target's `x86_64-unknown-none-gnu` default layout, `normalized data layout` + +error: aborting due to 1 previous error + From 0e961cd854c9b1752d00a2b53ec3b5b0ee668e34 Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Thu, 18 Jan 2024 18:53:41 +0800 Subject: [PATCH 126/676] fix suggestion error with attr macros --- clippy_lints/src/semicolon_if_nothing_returned.rs | 6 ++++++ tests/ui/semicolon_if_nothing_returned.fixed | 13 ++++++++++--- tests/ui/semicolon_if_nothing_returned.rs | 9 ++++++++- tests/ui/semicolon_if_nothing_returned.stderr | 14 +------------- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/semicolon_if_nothing_returned.rs b/clippy_lints/src/semicolon_if_nothing_returned.rs index 2cd3e57f885a2..6540626f7d5a3 100644 --- a/clippy_lints/src/semicolon_if_nothing_returned.rs +++ b/clippy_lints/src/semicolon_if_nothing_returned.rs @@ -5,6 +5,7 @@ use rustc_errors::Applicability; use rustc_hir::{Block, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; +use rustc_span::{ExpnKind, MacroKind, Span}; declare_clippy_lint! { /// ### What it does @@ -39,6 +40,7 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { if !block.span.from_expansion() && let Some(expr) = block.expr + && !from_attr_macro(expr.span) && let t_expr = cx.typeck_results().expr_ty(expr) && t_expr.is_unit() && let mut app = Applicability::MachineApplicable @@ -63,3 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned { } } } + +fn from_attr_macro(span: Span) -> bool { + matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Attr, _)) +} diff --git a/tests/ui/semicolon_if_nothing_returned.fixed b/tests/ui/semicolon_if_nothing_returned.fixed index bc96b959fc543..cdfa5d9cc7804 100644 --- a/tests/ui/semicolon_if_nothing_returned.fixed +++ b/tests/ui/semicolon_if_nothing_returned.fixed @@ -129,19 +129,26 @@ fn let_else_stmts() { mod issue12123 { #[rustfmt::skip] mod this_triggers { - #[fake_main]; + #[fake_main] async fn main() { - + } } mod and_this { - #[fake_main]; + #[fake_main] async fn main() { println!("hello"); } } + #[rustfmt::skip] + mod maybe_this { + /** */ #[fake_main] + async fn main() { + } + } + mod but_this_does_not { #[fake_main] async fn main() {} diff --git a/tests/ui/semicolon_if_nothing_returned.rs b/tests/ui/semicolon_if_nothing_returned.rs index e5713ce062bc0..315b7e4f38399 100644 --- a/tests/ui/semicolon_if_nothing_returned.rs +++ b/tests/ui/semicolon_if_nothing_returned.rs @@ -131,7 +131,7 @@ mod issue12123 { mod this_triggers { #[fake_main] async fn main() { - + } } @@ -142,6 +142,13 @@ mod issue12123 { } } + #[rustfmt::skip] + mod maybe_this { + /** */ #[fake_main] + async fn main() { + } + } + mod but_this_does_not { #[fake_main] async fn main() {} diff --git a/tests/ui/semicolon_if_nothing_returned.stderr b/tests/ui/semicolon_if_nothing_returned.stderr index 0d5381ef6212a..09c4d12f216c5 100644 --- a/tests/ui/semicolon_if_nothing_returned.stderr +++ b/tests/ui/semicolon_if_nothing_returned.stderr @@ -31,17 +31,5 @@ error: consider adding a `;` to the last statement for consistent formatting LL | ptr::drop_in_place(s.as_mut_ptr()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());` -error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:132:9 - | -LL | #[fake_main] - | ^^^^^^^^^^^^ help: add a `;` here: `#[fake_main];` - -error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:139:9 - | -LL | #[fake_main] - | ^^^^^^^^^^^^ help: add a `;` here: `#[fake_main];` - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors From 6a331e37fbe85cf69fa783bfc2fb2aba90d20bf6 Mon Sep 17 00:00:00 2001 From: Samuel Moelius <35515885+smoelius@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:32:57 -0500 Subject: [PATCH 127/676] Apply suggestions from code review Co-authored-by: fee1-dead --- clippy_utils/src/ty.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index a07d6587bf97c..59ebe685c11ee 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -219,7 +219,7 @@ pub fn implements_trait<'tcx>( /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. /// -/// The `callee_id` argument is used to determine the "effect arg", if one is needed. +/// The `callee_id` argument is used to determine whether this is a function call in a `const fn` environment, used for checking const traits. pub fn implements_trait_with_env<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, @@ -243,7 +243,9 @@ pub fn implements_trait_with_env_from_iter<'tcx>( // Clippy shouldn't have infer types assert!(!ty.has_infer()); - // If a `callee_id` is passed, then "assert" it is a body owner. + // If a `callee_id` is passed, then we assert that it is a body owner + // through calling `body_owner_kind`, which would panic if the callee + // does not have a body. if let Some(callee_id) = callee_id { let _ = tcx.hir().body_owner_kind(callee_id); } From 7a1e7d7df98301fecec0deeca318164c6732c1e6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 1 Feb 2023 14:23:51 +0000 Subject: [PATCH 128/676] Don't forget that the lifetime on hir types is `'tcx` --- .../src/default_union_representation.rs | 2 +- clippy_lints/src/implicit_hasher.rs | 2 +- clippy_lints/src/types/mod.rs | 18 +++++++++--------- clippy_lints/src/types/redundant_allocation.rs | 2 +- clippy_lints/src/types/vec_box.rs | 6 +++--- clippy_lints/src/unconditional_recursion.rs | 4 ++-- clippy_lints/src/uninhabited_references.rs | 6 +++--- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/zero_sized_map_values.rs | 4 ++-- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index db01ff2cd2205..bfd89bfd2c72f 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { /// (ZST fields having an arbitrary offset is completely inconsequential, and /// if there is only one field left after ignoring ZST fields then the offset /// of that field does not matter either.) -fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool { +fn is_union_with_two_non_zst_fields<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { if let ItemKind::Union(..) = &item.kind && let ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() { diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index 788fe82872784..87f6f5e7959e1 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -210,7 +210,7 @@ enum ImplicitHasherType<'tcx> { impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a `BuildHasher`. - fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option { + fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Option { if let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind { let params: Vec<_> = path .segments diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 81efec65343d1..7882bfdd09fad 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -314,9 +314,9 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn( &mut self, - cx: &LateContext<'_>, + cx: &LateContext<'tcx>, fn_kind: FnKind<'_>, - decl: &FnDecl<'_>, + decl: &FnDecl<'tcx>, _: &Body<'_>, _: Span, def_id: LocalDefId, @@ -346,7 +346,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { ); } - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); match item.kind { @@ -363,7 +363,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) { match item.kind { ImplItemKind::Const(ty, _) => { let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx @@ -391,7 +391,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { + fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &hir::FieldDef<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(field.def_id); self.check_ty( @@ -404,7 +404,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { ); } - fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); let context = CheckTyContext { @@ -421,7 +421,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) { if let Some(ty) = local.ty { self.check_ty( cx, @@ -444,7 +444,7 @@ impl Types { } } - fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) { + fn check_fn_decl<'tcx>(&mut self, cx: &LateContext<'tcx>, decl: &FnDecl<'tcx>, context: CheckTyContext) { // Ignore functions in trait implementations as they are usually forced by the trait definition. // // FIXME: ideally we would like to warn *if the complicated type can be simplified*, but it's hard @@ -466,7 +466,7 @@ impl Types { /// lint found. /// /// The parameter `is_local` distinguishes the context of the type. - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, mut context: CheckTyContext) { if hir_ty.span.from_expansion() { return; } diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs index 5a986254fad5e..a0d609501a0c0 100644 --- a/clippy_lints/src/types/redundant_allocation.rs +++ b/clippy_lints/src/types/redundant_allocation.rs @@ -11,7 +11,7 @@ use rustc_span::symbol::sym; use super::{utils, REDUNDANT_ALLOCATION}; -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: &QPath<'tcx>, def_id: DefId) -> bool { let mut applicability = Applicability::MaybeIncorrect; let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() { "Box" diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs index 9d5066199bde5..a285f771f1b1c 100644 --- a/clippy_lints/src/types/vec_box.rs +++ b/clippy_lints/src/types/vec_box.rs @@ -13,10 +13,10 @@ use rustc_span::symbol::sym; use super::VEC_BOX; -pub(super) fn check( - cx: &LateContext<'_>, +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, def_id: DefId, box_size_threshold: u64, ) -> bool { diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index e90306ded61c4..b418db53ea47c 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -77,7 +77,7 @@ fn get_ty_def_id(ty: Ty<'_>) -> Option { } } -fn get_hir_ty_def_id(tcx: TyCtxt<'_>, hir_ty: rustc_hir::Ty<'_>) -> Option { +fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Option { let TyKind::Path(qpath) = hir_ty.kind else { return None }; match qpath { QPath::Resolved(_, path) => path.res.opt_def_id(), @@ -229,7 +229,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local } } -fn is_default_method_on_current_ty(tcx: TyCtxt<'_>, qpath: QPath<'_>, implemented_ty_id: DefId) -> bool { +fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>, implemented_ty_id: DefId) -> bool { match qpath { QPath::Resolved(_, path) => match path.segments { [first, .., last] => last.ident.name == kw::Default && first.res.opt_def_id() == Some(implemented_ty_id), diff --git a/clippy_lints/src/uninhabited_references.rs b/clippy_lints/src/uninhabited_references.rs index 903593ecfd7df..6732a43a19ec5 100644 --- a/clippy_lints/src/uninhabited_references.rs +++ b/clippy_lints/src/uninhabited_references.rs @@ -57,11 +57,11 @@ impl LateLintPass<'_> for UninhabitedReferences { } } - fn check_fn( + fn check_fn<'tcx>( &mut self, - cx: &LateContext<'_>, + cx: &LateContext<'tcx>, kind: FnKind<'_>, - fndecl: &'_ FnDecl<'_>, + fndecl: &'_ FnDecl<'tcx>, _: &'_ Body<'_>, span: Span, _: LocalDefId, diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index fa033838ef355..a1b08d105b9d9 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { if !hir_ty.span.from_expansion() && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && let Some(&StackItem::Check { diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs index b36c4ef91dc61..81d4a26e9da43 100644 --- a/clippy_lints/src/zero_sized_map_values.rs +++ b/clippy_lints/src/zero_sized_map_values.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]); impl LateLintPass<'_> for ZeroSizedMapValues { - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { if !hir_ty.span.from_expansion() && !in_trait_impl(cx, hir_ty.hir_id) && let ty = ty_from_hir_ty(cx, hir_ty) @@ -82,7 +82,7 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { false } -fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { +fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { cx.maybe_typeck_results() .and_then(|results| { if results.hir_owner == hir_ty.hir_id.owner { From efd8dafa2f701280c2dd5ee31716ffa0c18e484b Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 18 Jan 2024 17:15:11 +0100 Subject: [PATCH 129/676] [`default_numeric_fallback`]: improve const context detection --- clippy_lints/src/default_numeric_fallback.rs | 14 +++---- tests/ui/default_numeric_fallback_i32.fixed | 40 ++++++++++++++++++++ tests/ui/default_numeric_fallback_i32.rs | 40 ++++++++++++++++++++ 3 files changed, 87 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs index 712bc075650fa..c4437a3c4b339 100644 --- a/clippy_lints/src/default_numeric_fallback.rs +++ b/clippy_lints/src/default_numeric_fallback.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::numeric_literal; use clippy_utils::source::snippet_opt; -use clippy_utils::{get_parent_node, numeric_literal}; use rustc_ast::ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor}; -use rustc_hir::{Block, Body, Expr, ExprKind, FnRetTy, HirId, ItemKind, Lit, Node, Stmt, StmtKind}; +use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty}; @@ -50,11 +50,11 @@ declare_lint_pass!(DefaultNumericFallback => [DEFAULT_NUMERIC_FALLBACK]); impl<'tcx> LateLintPass<'tcx> for DefaultNumericFallback { fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { - let is_parent_const = if let Some(Node::Item(item)) = get_parent_node(cx.tcx, body.id().hir_id) { - matches!(item.kind, ItemKind::Const(..)) - } else { - false - }; + let hir = cx.tcx.hir(); + let is_parent_const = matches!( + hir.body_const_context(hir.body_owner_def_id(body.id())), + Some(ConstContext::Const { inline: false } | ConstContext::Static(_)) + ); let mut visitor = NumericFallbackVisitor::new(cx, is_parent_const); visitor.visit_body(body); } diff --git a/tests/ui/default_numeric_fallback_i32.fixed b/tests/ui/default_numeric_fallback_i32.fixed index c364c6830578f..e7038082c089c 100644 --- a/tests/ui/default_numeric_fallback_i32.fixed +++ b/tests/ui/default_numeric_fallback_i32.fixed @@ -216,4 +216,44 @@ mod type_already_inferred { } } +mod issue12159 { + #![allow(non_upper_case_globals, clippy::exhaustive_structs)] + pub struct Foo; + + static F: i32 = 1; + impl Foo { + const LIFE_u8: u8 = 42; + const LIFE_i8: i8 = 42; + const LIFE_u16: u16 = 42; + const LIFE_i16: i16 = 42; + const LIFE_u32: u32 = 42; + const LIFE_i32: i32 = 42; + const LIFE_u64: u64 = 42; + const LIFE_i64: i64 = 42; + const LIFE_u128: u128 = 42; + const LIFE_i128: i128 = 42; + const LIFE_usize: usize = 42; + const LIFE_isize: isize = 42; + const LIFE_f32: f32 = 42.; + const LIFE_f64: f64 = 42.; + + const fn consts() { + const LIFE_u8: u8 = 42; + const LIFE_i8: i8 = 42; + const LIFE_u16: u16 = 42; + const LIFE_i16: i16 = 42; + const LIFE_u32: u32 = 42; + const LIFE_i32: i32 = 42; + const LIFE_u64: u64 = 42; + const LIFE_i64: i64 = 42; + const LIFE_u128: u128 = 42; + const LIFE_i128: i128 = 42; + const LIFE_usize: usize = 42; + const LIFE_isize: isize = 42; + const LIFE_f32: f32 = 42.; + const LIFE_f64: f64 = 42.; + } + } +} + fn main() {} diff --git a/tests/ui/default_numeric_fallback_i32.rs b/tests/ui/default_numeric_fallback_i32.rs index ffa7b961d1ced..d8eeda7049194 100644 --- a/tests/ui/default_numeric_fallback_i32.rs +++ b/tests/ui/default_numeric_fallback_i32.rs @@ -216,4 +216,44 @@ mod type_already_inferred { } } +mod issue12159 { + #![allow(non_upper_case_globals, clippy::exhaustive_structs)] + pub struct Foo; + + static F: i32 = 1; + impl Foo { + const LIFE_u8: u8 = 42; + const LIFE_i8: i8 = 42; + const LIFE_u16: u16 = 42; + const LIFE_i16: i16 = 42; + const LIFE_u32: u32 = 42; + const LIFE_i32: i32 = 42; + const LIFE_u64: u64 = 42; + const LIFE_i64: i64 = 42; + const LIFE_u128: u128 = 42; + const LIFE_i128: i128 = 42; + const LIFE_usize: usize = 42; + const LIFE_isize: isize = 42; + const LIFE_f32: f32 = 42.; + const LIFE_f64: f64 = 42.; + + const fn consts() { + const LIFE_u8: u8 = 42; + const LIFE_i8: i8 = 42; + const LIFE_u16: u16 = 42; + const LIFE_i16: i16 = 42; + const LIFE_u32: u32 = 42; + const LIFE_i32: i32 = 42; + const LIFE_u64: u64 = 42; + const LIFE_i64: i64 = 42; + const LIFE_u128: u128 = 42; + const LIFE_i128: i128 = 42; + const LIFE_usize: usize = 42; + const LIFE_isize: isize = 42; + const LIFE_f32: f32 = 42.; + const LIFE_f64: f64 = 42.; + } + } +} + fn main() {} From baa2cf5ea610d10be1e3cb13f7da4f2d752aa69a Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Fri, 19 Jan 2024 09:26:56 +1100 Subject: [PATCH 130/676] Update `std::io::Error::downcast` return type and update its doc according to decision made by rust libs-api team. Signed-off-by: Jiahao XU --- library/std/src/io/error.rs | 36 ++++++++++++++++++++++++++----- library/std/src/io/error/tests.rs | 4 ++-- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index b63091deac27e..13cc0511e103e 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -816,12 +816,12 @@ impl Error { } } - /// Attempt to downgrade the inner error to `E` if any. + /// Attempt to downcast the inner error to `E` if any. /// /// If this [`Error`] was constructed via [`new`] then this function will /// attempt to perform downgrade on it, otherwise it will return [`Err`]. /// - /// If downgrade succeeds, it will return [`Ok`], otherwise it will also + /// If the downcast succeeds, it will return [`Ok`], otherwise it will also /// return [`Err`]. /// /// [`new`]: Error::new @@ -852,13 +852,39 @@ impl Error { /// impl From for E { /// fn from(err: io::Error) -> E { /// err.downcast::() - /// .map(|b| *b) /// .unwrap_or_else(E::Io) /// } /// } + /// + /// impl From for io::Error { + /// fn from(err: E) -> io::Error { + /// match err { + /// E::Io(io_error) => io_error, + /// e => io::Error::new(io::ErrorKind::Other, e), + /// } + /// } + /// } + /// + /// # fn main() { + /// let e = E::SomeOtherVariant; + /// // Convert it to an io::Error + /// let io_error = io::Error::from(e); + /// // Cast it back to the original variant + /// let e = E::from(io_error); + /// assert!(matches!(e, E::SomeOtherVariant)); + /// + /// let io_error = io::Error::from(io::ErrorKind::AlreadyExists); + /// // Convert it to E + /// let e = E::from(io_error); + /// // Cast it back to the original variant + /// let io_error = io::Error::from(e); + /// assert_eq!(io_error.kind(), io::ErrorKind::AlreadyExists); + /// assert!(io_error.get_ref().is_none()); + /// assert!(io_error.raw_os_error().is_none()); + /// # } /// ``` #[unstable(feature = "io_error_downcast", issue = "99262")] - pub fn downcast(self) -> result::Result, Self> + pub fn downcast(self) -> result::Result where E: error::Error + Send + Sync + 'static, { @@ -872,7 +898,7 @@ impl Error { // And the compiler should be able to eliminate the branch // that produces `Err` here since b.error.is::() // returns true. - Ok(res.unwrap()) + Ok(*res.unwrap()) } repr_data => Err(Self { repr: Repr::new(repr_data) }), } diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs index 36d52aef03cb7..fc6db2825e811 100644 --- a/library/std/src/io/error/tests.rs +++ b/library/std/src/io/error/tests.rs @@ -157,7 +157,7 @@ impl error::Error for E {} fn test_std_io_error_downcast() { // Case 1: custom error, downcast succeeds let io_error = Error::new(ErrorKind::Other, Bojji(true)); - let e: Box = io_error.downcast().unwrap(); + let e: Bojji = io_error.downcast().unwrap(); assert!(e.0); // Case 2: custom error, downcast fails @@ -166,7 +166,7 @@ fn test_std_io_error_downcast() { // ensures that the custom error is intact assert_eq!(ErrorKind::Other, io_error.kind()); - let e: Box = io_error.downcast().unwrap(); + let e: Bojji = io_error.downcast().unwrap(); assert!(e.0); // Case 3: os error From c6079a6880ffa29a49edeb48520f220963b01c3e Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 19 Jan 2024 01:06:08 +0100 Subject: [PATCH 131/676] blocks_in_conditions: do not warn if condition comes from macro --- clippy_lints/src/blocks_in_conditions.rs | 5 +++++ tests/ui/blocks_in_conditions.fixed | 14 ++++++++++++++ tests/ui/blocks_in_conditions.rs | 14 ++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/clippy_lints/src/blocks_in_conditions.rs b/clippy_lints/src/blocks_in_conditions.rs index 1417e230aee5f..ff4dffd06079f 100644 --- a/clippy_lints/src/blocks_in_conditions.rs +++ b/clippy_lints/src/blocks_in_conditions.rs @@ -67,6 +67,11 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { ); if let ExprKind::Block(block, _) = &cond.kind { + if !block.span.eq_ctxt(expr.span) { + // If the block comes from a macro, or as an argument to a macro, + // do not lint. + return; + } if block.rules == BlockCheckMode::DefaultBlock { if block.stmts.is_empty() { if let Some(ex) = &block.expr { diff --git a/tests/ui/blocks_in_conditions.fixed b/tests/ui/blocks_in_conditions.fixed index 2ab441bbd0c69..efef60567a979 100644 --- a/tests/ui/blocks_in_conditions.fixed +++ b/tests/ui/blocks_in_conditions.fixed @@ -85,4 +85,18 @@ fn block_in_match_expr(num: i32) -> i32 { } } +// issue #12162 +macro_rules! timed { + ($name:expr, $body:expr $(,)?) => {{ + let __scope = (); + $body + }}; +} + +fn issue_12162() { + if timed!("check this!", false) { + println!(); + } +} + fn main() {} diff --git a/tests/ui/blocks_in_conditions.rs b/tests/ui/blocks_in_conditions.rs index dd5ae4fb486b7..8bd8a939eb16e 100644 --- a/tests/ui/blocks_in_conditions.rs +++ b/tests/ui/blocks_in_conditions.rs @@ -85,4 +85,18 @@ fn block_in_match_expr(num: i32) -> i32 { } } +// issue #12162 +macro_rules! timed { + ($name:expr, $body:expr $(,)?) => {{ + let __scope = (); + $body + }}; +} + +fn issue_12162() { + if timed!("check this!", false) { + println!(); + } +} + fn main() {} From 9661f9b17773d20efb11b77d4fc59d4d8daae4f9 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 19 Jan 2024 15:01:33 +0800 Subject: [PATCH 132/676] Add new condition to avoid derived code trigger lint --- clippy_lints/src/no_effect.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 2a2c2b331ba79..55b23a1f71892 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::has_drop; -use clippy_utils::{get_parent_node, is_lint_allowed, peel_blocks}; +use clippy_utils::{any_parent_is_automatically_derived, get_parent_node, is_lint_allowed, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ @@ -144,6 +144,7 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { } } else if let StmtKind::Local(local) = stmt.kind { if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) + && !any_parent_is_automatically_derived(cx.tcx, local.hir_id) && let Some(init) = local.init && local.els.is_none() && !local.pat.span.from_expansion() From 73d7ce6abf877f22c7355b3b203e1587e58741bd Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 19 Jan 2024 21:05:58 +0800 Subject: [PATCH 133/676] Move the new check to the end of checks --- clippy_lints/src/no_effect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 55b23a1f71892..5983e20689414 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -144,13 +144,13 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { } } else if let StmtKind::Local(local) = stmt.kind { if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) - && !any_parent_is_automatically_derived(cx.tcx, local.hir_id) && let Some(init) = local.init && local.els.is_none() && !local.pat.span.from_expansion() && has_no_effect(cx, init) && let PatKind::Binding(_, _, ident, _) = local.pat.kind && ident.name.to_ident_string().starts_with('_') + && !any_parent_is_automatically_derived(cx.tcx, local.hir_id) { span_lint_hir( cx, From 6267b6ca09b4a91c83bd11a72aeffaf96fa55702 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 19 Jan 2024 23:25:36 +0100 Subject: [PATCH 134/676] no_effect_underscore_binding: _ prefixed variables can be used Prefixing a variable with a `_` does not mean that it will not be used. If such a variable is used later, do not warn about the fact that its initialization does not have a side effect as this is fine. --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/no_effect.rs | 180 ++++++++++++++++++++-------------- tests/ui/no_effect.rs | 2 + 3 files changed, 109 insertions(+), 75 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index efdd392594977..8004590e8e75d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -719,7 +719,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(needless_update::NeedlessUpdate)); store.register_late_pass(|_| Box::new(needless_borrowed_ref::NeedlessBorrowedRef)); store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef)); - store.register_late_pass(|_| Box::new(no_effect::NoEffect)); + store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment)); store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv()))); store.register_late_pass(move |_| { diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 5983e20689414..0d234f7f9b52c 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,16 +1,18 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::has_drop; -use clippy_utils::{any_parent_is_automatically_derived, get_parent_node, is_lint_allowed, peel_blocks}; +use clippy_utils::{any_parent_is_automatically_derived, get_parent_node, is_lint_allowed, path_to_local, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ - is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, ItemKind, Node, PatKind, Stmt, StmtKind, UnsafeSource, + is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, HirId, HirIdMap, ItemKind, Node, PatKind, Stmt, + StmtKind, UnsafeSource, }; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; +use rustc_span::Span; use std::ops::Deref; declare_clippy_lint! { @@ -74,95 +76,125 @@ declare_clippy_lint! { "outer expressions with no effect" } -declare_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION, NO_EFFECT_UNDERSCORE_BINDING]); +#[derive(Default)] +pub struct NoEffect { + underscore_bindings: HirIdMap, + local_bindings: Vec>, +} + +impl_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION, NO_EFFECT_UNDERSCORE_BINDING]); impl<'tcx> LateLintPass<'tcx> for NoEffect { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if check_no_effect(cx, stmt) { + if self.check_no_effect(cx, stmt) { return; } check_unnecessary_operation(cx, stmt); } -} -fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { - if let StmtKind::Semi(expr) = stmt.kind { - // move `expr.span.from_expansion()` ahead - if expr.span.from_expansion() { - return false; + fn check_block(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Block<'tcx>) { + self.local_bindings.push(Vec::default()); + } + + fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx rustc_hir::Block<'tcx>) { + for hir_id in self.local_bindings.pop().unwrap() { + if let Some(span) = self.underscore_bindings.remove(&hir_id) { + span_lint_hir( + cx, + NO_EFFECT_UNDERSCORE_BINDING, + hir_id, + span, + "binding to `_` prefixed variable with no side-effect", + ); + } } - let expr = peel_blocks(expr); + } - if is_operator_overridden(cx, expr) { - // Return `true`, to prevent `check_unnecessary_operation` from - // linting on this statement as well. - return true; + fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { + if let Some(def_id) = path_to_local(expr) { + self.underscore_bindings.remove(&def_id); } - if has_no_effect(cx, expr) { - span_lint_hir_and_then( - cx, - NO_EFFECT, - expr.hir_id, - stmt.span, - "statement with no effect", - |diag| { - for parent in cx.tcx.hir().parent_iter(stmt.hir_id) { - if let Node::Item(item) = parent.1 - && let ItemKind::Fn(..) = item.kind - && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id) - && let [.., final_stmt] = block.stmts - && final_stmt.hir_id == stmt.hir_id - { - let expr_ty = cx.typeck_results().expr_ty(expr); - let mut ret_ty = cx - .tcx - .fn_sig(item.owner_id) - .instantiate_identity() - .output() - .skip_binder(); + } +} - // Remove `impl Future` to get `T` - if cx.tcx.ty_is_opaque_future(ret_ty) - && let Some(true_ret_ty) = cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty) +impl NoEffect { + fn check_no_effect(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { + if let StmtKind::Semi(expr) = stmt.kind { + // move `expr.span.from_expansion()` ahead + if expr.span.from_expansion() { + return false; + } + let expr = peel_blocks(expr); + + if is_operator_overridden(cx, expr) { + // Return `true`, to prevent `check_unnecessary_operation` from + // linting on this statement as well. + return true; + } + if has_no_effect(cx, expr) { + span_lint_hir_and_then( + cx, + NO_EFFECT, + expr.hir_id, + stmt.span, + "statement with no effect", + |diag| { + for parent in cx.tcx.hir().parent_iter(stmt.hir_id) { + if let Node::Item(item) = parent.1 + && let ItemKind::Fn(..) = item.kind + && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id) + && let [.., final_stmt] = block.stmts + && final_stmt.hir_id == stmt.hir_id { - ret_ty = true_ret_ty; - } + let expr_ty = cx.typeck_results().expr_ty(expr); + let mut ret_ty = cx + .tcx + .fn_sig(item.owner_id) + .instantiate_identity() + .output() + .skip_binder(); + + // Remove `impl Future` to get `T` + if cx.tcx.ty_is_opaque_future(ret_ty) + && let Some(true_ret_ty) = + cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty) + { + ret_ty = true_ret_ty; + } - if !ret_ty.is_unit() && ret_ty == expr_ty { - diag.span_suggestion( - stmt.span.shrink_to_lo(), - "did you mean to return it?", - "return ", - Applicability::MaybeIncorrect, - ); + if !ret_ty.is_unit() && ret_ty == expr_ty { + diag.span_suggestion( + stmt.span.shrink_to_lo(), + "did you mean to return it?", + "return ", + Applicability::MaybeIncorrect, + ); + } } } - } - }, - ); - return true; - } - } else if let StmtKind::Local(local) = stmt.kind { - if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) - && let Some(init) = local.init - && local.els.is_none() - && !local.pat.span.from_expansion() - && has_no_effect(cx, init) - && let PatKind::Binding(_, _, ident, _) = local.pat.kind - && ident.name.to_ident_string().starts_with('_') - && !any_parent_is_automatically_derived(cx.tcx, local.hir_id) - { - span_lint_hir( - cx, - NO_EFFECT_UNDERSCORE_BINDING, - init.hir_id, - ident.span, - "binding to `_` prefixed variable with no side-effect", - ); - return true; + }, + ); + return true; + } + } else if let StmtKind::Local(local) = stmt.kind { + if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) + && let Some(init) = local.init + && local.els.is_none() + && !local.pat.span.from_expansion() + && has_no_effect(cx, init) + && let PatKind::Binding(_, hir_id, ident, _) = local.pat.kind + && ident.name.to_ident_string().starts_with('_') + && !any_parent_is_automatically_derived(cx.tcx, local.hir_id) + { + if let Some(l) = self.local_bindings.last_mut() { + l.push(hir_id); + self.underscore_bindings.insert(hir_id, ident.span); + } + return true; + } } + false } - false } fn is_operator_overridden(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 777b1e52c2da6..dabeda72f0c8c 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -181,6 +181,8 @@ fn main() { //~^ ERROR: binding to `_` prefixed variable with no side-effect let _cat = [2, 4, 6, 8][2]; //~^ ERROR: binding to `_` prefixed variable with no side-effect + let _issue_12166 = 42; + let underscore_variable_above_can_be_used_dont_lint = _issue_12166; #[allow(clippy::no_effect)] 0; From eb42f3e70309eec46e266f74598334e576d6583e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 17 Jan 2024 15:40:30 -0800 Subject: [PATCH 135/676] Pack the u128 in LitKind::Int --- clippy_lints/src/casts/unnecessary_cast.rs | 2 +- clippy_lints/src/implicit_saturating_add.rs | 3 ++- clippy_lints/src/implicit_saturating_sub.rs | 3 ++- clippy_lints/src/loops/manual_memcpy.rs | 2 +- clippy_lints/src/loops/needless_range_loop.rs | 4 ++-- clippy_lints/src/manual_bits.rs | 3 ++- clippy_lints/src/manual_range_patterns.rs | 2 +- clippy_lints/src/manual_strip.rs | 2 +- clippy_lints/src/matches/match_same_arms.rs | 6 ++--- clippy_lints/src/methods/get_first.rs | 3 ++- .../src/methods/iter_out_of_bounds.rs | 2 +- clippy_lints/src/methods/seek_from_current.rs | 3 ++- .../seek_to_start_instead_of_rewind.rs | 3 ++- clippy_lints/src/methods/unnecessary_fold.rs | 5 ++-- .../src/methods/vec_resize_to_zero.rs | 3 ++- .../src/missing_asserts_for_indexing.rs | 23 ++++++++++--------- .../src/operators/arithmetic_side_effects.rs | 2 +- .../src/operators/verbose_bit_mask.rs | 5 ++-- clippy_utils/src/consts.rs | 2 +- clippy_utils/src/lib.rs | 3 ++- 20 files changed, 46 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 3761ba81f5219..bb86b6f30759c 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -107,7 +107,7 @@ pub(super) fn check<'tcx>( && let Some(src) = snippet_opt(cx, cast_expr.span) && cast_to.is_floating_point() && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) - && let from_nbits = 128 - n.leading_zeros() + && let from_nbits = 128 - n.get().leading_zeros() && let to_nbits = fp_ty_mantissa_nbits(cast_to) && from_nbits != 0 && to_nbits != 0 diff --git a/clippy_lints/src/implicit_saturating_add.rs b/clippy_lints/src/implicit_saturating_add.rs index cc74844f29427..b8d7e8f3b07c7 100644 --- a/clippy_lints/src/implicit_saturating_add.rs +++ b/clippy_lints/src/implicit_saturating_add.rs @@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_context; use rustc_ast::ast::{LitIntType, LitKind}; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -69,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd { && clippy_utils::SpanlessEq::new(cx).eq_expr(l, target) && BinOpKind::Add == op1.node && let ExprKind::Lit(lit) = value.kind - && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node + && let LitKind::Int(Pu128(1), LitIntType::Unsuffixed) = lit.node && block.expr.is_none() { let mut app = Applicability::MachineApplicable; diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 81df1a889c789..127c73ed637b2 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq}; use rustc_ast::ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; @@ -86,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { match cond_num_val.kind { ExprKind::Lit(cond_lit) => { // Check if the constant is zero - if let LitKind::Int(0, _) = cond_lit.node { + if let LitKind::Int(Pu128(0), _) = cond_lit.node { if cx.typeck_results().expr_ty(cond_left).is_signed() { } else { print_lint_and_sugg(cx, var_name, expr); diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index fda6c9749d434..58f713d81871f 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -461,7 +461,7 @@ fn is_array_length_equal_to_range(cx: &LateContext<'_>, start: &Expr<'_>, end: & if let ExprKind::Lit(lit) = expr.kind && let ast::LitKind::Int(value, _) = lit.node { - Some(value) + Some(value.get()) } else { None } diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index 4acf46f73c902..08b8a9e2ff072 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -209,8 +209,8 @@ fn is_end_eq_array_len<'tcx>( && let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env) { return match limits { - ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(), - ast::RangeLimits::HalfOpen => end_int >= arr_len.into(), + ast::RangeLimits::Closed => end_int.get() + 1 >= arr_len.into(), + ast::RangeLimits::HalfOpen => end_int.get() >= arr_len.into(), }; } diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index 96c652283daa5..aa02e4e7a434f 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_context; use rustc_ast::ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -62,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { && let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr) && matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_)) && let ExprKind::Lit(lit) = &other_expr.kind - && let LitKind::Int(8, _) = lit.node + && let LitKind::Int(Pu128(8), _) = lit.node { let mut app = Applicability::MachineApplicable; let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0; diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs index d585290f7773c..ec60de92c4ba2 100644 --- a/clippy_lints/src/manual_range_patterns.rs +++ b/clippy_lints/src/manual_range_patterns.rs @@ -45,7 +45,7 @@ fn expr_as_i128(expr: &Expr<'_>) -> Option { && let LitKind::Int(num, _) = lit.node { // Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now. - num.try_into().ok() + num.get().try_into().ok() } else { None } diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 7b04fd28b896f..bcd0243600245 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -161,7 +161,7 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t .. }) = expr.kind { - constant_length(cx, pattern).map_or(false, |length| length == *n) + constant_length(cx, pattern).map_or(false, |length| *n == length) } else { len_arg(cx, expr).map_or(false, |arg| eq_expr_value(cx, pattern, arg)) } diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index 5ca161e93096d..d645e6c6c05c9 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -293,7 +293,7 @@ impl<'a> NormalizedPat<'a> { LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes), LitKind::Byte(val) => Self::LitInt(val.into()), LitKind::Char(val) => Self::LitInt(val.into()), - LitKind::Int(val, _) => Self::LitInt(val), + LitKind::Int(val, _) => Self::LitInt(val.get()), LitKind::Bool(val) => Self::LitBool(val), LitKind::Float(..) | LitKind::Err => Self::Wild, }, @@ -305,7 +305,7 @@ impl<'a> NormalizedPat<'a> { None => 0, Some(e) => match &e.kind { ExprKind::Lit(lit) => match lit.node { - LitKind::Int(val, _) => val, + LitKind::Int(val, _) => val.get(), LitKind::Char(val) => val.into(), LitKind::Byte(val) => val.into(), _ => return Self::Wild, @@ -317,7 +317,7 @@ impl<'a> NormalizedPat<'a> { None => (u128::MAX, RangeEnd::Included), Some(e) => match &e.kind { ExprKind::Lit(lit) => match lit.node { - LitKind::Int(val, _) => (val, bounds), + LitKind::Int(val, _) => (val.get(), bounds), LitKind::Char(val) => (val.into(), bounds), LitKind::Byte(val) => (val.into(), bounds), _ => return Self::Wild, diff --git a/clippy_lints/src/methods/get_first.rs b/clippy_lints/src/methods/get_first.rs index e1f1e4893558e..55fcf37289404 100644 --- a/clippy_lints/src/methods/get_first.rs +++ b/clippy_lints/src/methods/get_first.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -20,7 +21,7 @@ pub(super) fn check<'tcx>( && let Some(impl_id) = cx.tcx.impl_of_method(method_id) && let identity = cx.tcx.type_of(impl_id).instantiate_identity() && let hir::ExprKind::Lit(Spanned { - node: LitKind::Int(0, _), + node: LitKind::Int(Pu128(0), _), .. }) = arg.kind { diff --git a/clippy_lints/src/methods/iter_out_of_bounds.rs b/clippy_lints/src/methods/iter_out_of_bounds.rs index 29e69b111de6e..f198849c5c0c6 100644 --- a/clippy_lints/src/methods/iter_out_of_bounds.rs +++ b/clippy_lints/src/methods/iter_out_of_bounds.rs @@ -13,7 +13,7 @@ fn expr_as_u128(cx: &LateContext<'_>, e: &Expr<'_>) -> Option { if let ExprKind::Lit(lit) = expr_or_init(cx, e).kind && let LitKind::Int(n, _) = lit.node { - Some(n) + Some(n.get()) } else { None } diff --git a/clippy_lints/src/methods/seek_from_current.rs b/clippy_lints/src/methods/seek_from_current.rs index 63d41677feed2..e45c7962f13f4 100644 --- a/clippy_lints/src/methods/seek_from_current.rs +++ b/clippy_lints/src/methods/seek_from_current.rs @@ -1,4 +1,5 @@ use rustc_ast::ast::{LitIntType, LitKind}; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -41,7 +42,7 @@ fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) // check if argument of `SeekFrom::Current` is `0` if args.len() == 1 && let ExprKind::Lit(lit) = args[0].kind - && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node + && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node { return true; } diff --git a/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs index 9f38460357ba6..cc4cb47e35c63 100644 --- a/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs +++ b/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::implements_trait; use clippy_utils::{is_expr_used_or_unified, match_def_path, paths}; use rustc_ast::ast::{LitIntType, LitKind}; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -31,7 +32,7 @@ pub(super) fn check<'tcx>( && match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START) && args1.len() == 1 && let ExprKind::Lit(lit) = args1[0].kind - && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node + && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node { let method_call_span = expr.span.with_lo(name_span.lo()); span_lint_and_then( diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index ebbdde48b450f..f3577ef6082bf 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_trait_method, path_to_local_id, peel_blocks, strip_pat_refs}; use rustc_ast::ast; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::PatKind; @@ -150,7 +151,7 @@ pub(super) fn check( }, ); }, - ast::LitKind::Int(0, _) => check_fold_with_op( + ast::LitKind::Int(Pu128(0), _) => check_fold_with_op( cx, expr, acc, @@ -162,7 +163,7 @@ pub(super) fn check( method_name: "sum", }, ), - ast::LitKind::Int(1, _) => { + ast::LitKind::Int(Pu128(1), _) => { check_fold_with_op( cx, expr, diff --git a/clippy_lints/src/methods/vec_resize_to_zero.rs b/clippy_lints/src/methods/vec_resize_to_zero.rs index 9e87fb45aa65a..3e271a606115a 100644 --- a/clippy_lints/src/methods/vec_resize_to_zero.rs +++ b/clippy_lints/src/methods/vec_resize_to_zero.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -20,7 +21,7 @@ pub(super) fn check<'tcx>( && let Some(impl_id) = cx.tcx.impl_of_method(method_id) && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Vec) && let ExprKind::Lit(Spanned { - node: LitKind::Int(0, _), + node: LitKind::Int(Pu128(0), _), .. }) = count_arg.kind && let ExprKind::Lit(Spanned { diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs index bbc4d0a0f9a54..0e4d39c999020 100644 --- a/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/clippy_lints/src/missing_asserts_for_indexing.rs @@ -7,6 +7,7 @@ use clippy_utils::source::snippet; use clippy_utils::visitors::for_each_expr; use clippy_utils::{eq_expr_value, hash_expr, higher}; use rustc_ast::{LitKind, RangeLimits}; +use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; @@ -102,8 +103,8 @@ fn len_comparison<'hir>( ) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> { macro_rules! int_lit_pat { ($id:ident) => { - ExprKind::Lit(Spanned { - node: LitKind::Int($id, _), + ExprKind::Lit(&Spanned { + node: LitKind::Int(Pu128($id), _), .. }) }; @@ -112,13 +113,13 @@ fn len_comparison<'hir>( // normalize comparison, `v.len() > 4` becomes `4 < v.len()` // this simplifies the logic a bit let (op, left, right) = normalize_comparison(bin_op.node, left, right)?; - match (op, &left.kind, &right.kind) { - (Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, *left as usize, right)), - (Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, *right as usize, left)), - (Rel::Le, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanOrEqualLength, *left as usize, right)), - (Rel::Le, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanOrEqualInt, *right as usize, left)), - (Rel::Eq, int_lit_pat!(left), _) => Some((LengthComparison::LengthEqualInt, *left as usize, right)), - (Rel::Eq, _, int_lit_pat!(right)) => Some((LengthComparison::LengthEqualInt, *right as usize, left)), + match (op, left.kind, right.kind) { + (Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, left as usize, right)), + (Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, right as usize, left)), + (Rel::Le, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanOrEqualLength, left as usize, right)), + (Rel::Le, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanOrEqualInt, right as usize, left)), + (Rel::Eq, int_lit_pat!(left), _) => Some((LengthComparison::LengthEqualInt, left as usize, right)), + (Rel::Eq, _, int_lit_pat!(right)) => Some((LengthComparison::LengthEqualInt, right as usize, left)), _ => None, } } @@ -206,14 +207,14 @@ impl<'hir> IndexEntry<'hir> { /// for `..=5` this returns `Some(5)` fn upper_index_expr(expr: &Expr<'_>) -> Option { if let ExprKind::Lit(lit) = &expr.kind - && let LitKind::Int(index, _) = lit.node + && let LitKind::Int(Pu128(index), _) = lit.node { Some(index as usize) } else if let Some(higher::Range { end: Some(end), limits, .. }) = higher::Range::hir(expr) && let ExprKind::Lit(lit) = &end.kind - && let LitKind::Int(index @ 1.., _) = lit.node + && let LitKind::Int(Pu128(index @ 1..), _) = lit.node { match limits { RangeLimits::HalfOpen => Some(index as usize - 1), diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index c081dec9b6b75..929efb6c574d5 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -151,7 +151,7 @@ impl ArithmeticSideEffects { if let hir::ExprKind::Lit(lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node { - return Some(n); + return Some(n.get()); } if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) { return Some(n); diff --git a/clippy_lints/src/operators/verbose_bit_mask.rs b/clippy_lints/src/operators/verbose_bit_mask.rs index fbf65e92b322a..a6aba33e431a4 100644 --- a/clippy_lints/src/operators/verbose_bit_mask.rs +++ b/clippy_lints/src/operators/verbose_bit_mask.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::Sugg; use rustc_ast::ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -19,9 +20,9 @@ pub(super) fn check<'tcx>( && let ExprKind::Binary(op1, left1, right1) = &left.kind && BinOpKind::BitAnd == op1.node && let ExprKind::Lit(lit) = &right1.kind - && let LitKind::Int(n, _) = lit.node + && let LitKind::Int(Pu128(n), _) = lit.node && let ExprKind::Lit(lit1) = &right.kind - && let LitKind::Int(0, _) = lit1.node + && let LitKind::Int(Pu128(0), _) = lit1.node && n.leading_zeros() == n.count_zeros() && n > u128::from(threshold) { diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 727f93c832742..61b38391d9e09 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -275,7 +275,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option>) -> Constan LitKind::Byte(b) => Constant::Int(u128::from(b)), LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)), LitKind::Char(c) => Constant::Char(c), - LitKind::Int(n, _) => Constant::Int(n), + LitKind::Int(n, _) => Constant::Int(n.get()), LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty { ast::FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()), ast::FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()), diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index d264e46f13320..ebe520b27eb56 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -80,6 +80,7 @@ use std::sync::{Mutex, MutexGuard, OnceLock}; use itertools::Itertools; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, LOCAL_CRATE}; @@ -838,7 +839,7 @@ pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { match &e.kind { ExprKind::Lit(lit) => match lit.node { - LitKind::Bool(false) | LitKind::Int(0, _) => true, + LitKind::Bool(false) | LitKind::Int(Pu128(0), _) => true, LitKind::Str(s, _) => s.is_empty(), _ => false, }, 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 136/676] 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 137/676] 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 138/676] 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 139/676] 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 140/676] 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 141/676] 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 142/676] 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 143/676] 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 144/676] 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 145/676] 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 146/676] 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 147/676] 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 148/676] 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 149/676] 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 150/676] 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 151/676] 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 49b0c3f4f1b43e5dcac88c965c32a8e804d7fb3c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 18 Jan 2024 18:17:46 +0100 Subject: [PATCH 152/676] Improve wording for suggestion messages --- clippy_lints/src/loops/same_item_push.rs | 2 +- clippy_lints/src/methods/join_absolute_paths.rs | 2 +- clippy_lints/src/methods/manual_saturating_arithmetic.rs | 2 +- clippy_lints/src/methods/option_as_ref_deref.rs | 2 +- clippy_lints/src/methods/option_map_or_err_ok.rs | 2 +- clippy_lints/src/methods/option_map_or_none.rs | 6 +++--- clippy_lints/src/methods/result_map_or_else_none.rs | 2 +- clippy_lints/src/methods/single_char_pattern.rs | 2 +- clippy_lints/src/methods/unnecessary_join.rs | 2 +- .../internal_lints/almost_standard_lint_formulation.rs | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index c245eaf1ab44d..920a887a6fd1b 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -31,7 +31,7 @@ pub(super) fn check<'tcx>( vec.span, "it looks like the same item is being pushed into this Vec", None, - &format!("try using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"), + &format!("consider using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"), ); } diff --git a/clippy_lints/src/methods/join_absolute_paths.rs b/clippy_lints/src/methods/join_absolute_paths.rs index 02f28779cf6ee..aa1ec60d434a5 100644 --- a/clippy_lints/src/methods/join_absolute_paths.rs +++ b/clippy_lints/src/methods/join_absolute_paths.rs @@ -42,7 +42,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a ) .span_suggestion( expr_span, - "if this is intentional, try using `Path::new` instead", + "if this is intentional, consider using `Path::new`", format!("PathBuf::from({arg_str})"), Applicability::Unspecified, ); diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs index 04bdbc1ea25fe..bf437db7e72ab 100644 --- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -50,7 +50,7 @@ pub fn check( super::MANUAL_SATURATING_ARITHMETIC, expr.span, "manual saturating arithmetic", - &format!("try using `saturating_{arith}`"), + &format!("consider using `saturating_{arith}`"), format!( "{}.saturating_{arith}({})", snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability), diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 756dbe62d84d6..88e2af15658ff 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -97,7 +97,7 @@ pub(super) fn check( }; let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" }; let hint = format!("{}.{method_hint}()", snippet(cx, as_ref_recv.span, "..")); - let suggestion = format!("try using {method_hint} instead"); + let suggestion = format!("consider using {method_hint}"); let msg = format!("called `{current_method}` on an `Option` value"); span_lint_and_sugg( diff --git a/clippy_lints/src/methods/option_map_or_err_ok.rs b/clippy_lints/src/methods/option_map_or_err_ok.rs index 91e39d5a1cd27..4e424d4c066a6 100644 --- a/clippy_lints/src/methods/option_map_or_err_ok.rs +++ b/clippy_lints/src/methods/option_map_or_err_ok.rs @@ -33,7 +33,7 @@ pub(super) fn check<'tcx>( OPTION_MAP_OR_ERR_OK, expr.span, msg, - "try using `ok_or` instead", + "consider using `ok_or`", format!("{self_snippet}.ok_or({err_snippet})"), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/option_map_or_none.rs b/clippy_lints/src/methods/option_map_or_none.rs index ff4d8cc9e3e1a..193deafccf650 100644 --- a/clippy_lints/src/methods/option_map_or_none.rs +++ b/clippy_lints/src/methods/option_map_or_none.rs @@ -72,7 +72,7 @@ pub(super) fn check<'tcx>( OPTION_MAP_OR_NONE, expr.span, msg, - "try using `map` instead", + "consider using `map`", format!("{self_snippet}.map({arg_snippet} {func_snippet})"), Applicability::MachineApplicable, ); @@ -85,7 +85,7 @@ pub(super) fn check<'tcx>( OPTION_MAP_OR_NONE, expr.span, msg, - "try using `and_then` instead", + "consider using `and_then`", format!("{self_snippet}.and_then({func_snippet})"), Applicability::MachineApplicable, ); @@ -97,7 +97,7 @@ pub(super) fn check<'tcx>( RESULT_MAP_OR_INTO_OPTION, expr.span, msg, - "try using `ok` instead", + "consider using `ok`", format!("{self_snippet}.ok()"), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/result_map_or_else_none.rs b/clippy_lints/src/methods/result_map_or_else_none.rs index bc16a11281620..3b0dc506305b5 100644 --- a/clippy_lints/src/methods/result_map_or_else_none.rs +++ b/clippy_lints/src/methods/result_map_or_else_none.rs @@ -34,7 +34,7 @@ pub(super) fn check<'tcx>( RESULT_MAP_OR_INTO_OPTION, expr.span, msg, - "try using `ok` instead", + "consider using `ok`", format!("{self_snippet}.ok()"), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/single_char_pattern.rs b/clippy_lints/src/methods/single_char_pattern.rs index 3983f0c0cabd4..363b1f2b81229 100644 --- a/clippy_lints/src/methods/single_char_pattern.rs +++ b/clippy_lints/src/methods/single_char_pattern.rs @@ -57,7 +57,7 @@ pub(super) fn check( SINGLE_CHAR_PATTERN, arg.span, "single-character string constant used as pattern", - "try using a `char` instead", + "consider using a `char`", hint, applicability, ); diff --git a/clippy_lints/src/methods/unnecessary_join.rs b/clippy_lints/src/methods/unnecessary_join.rs index e2b389e96dae0..c3ad4db387592 100644 --- a/clippy_lints/src/methods/unnecessary_join.rs +++ b/clippy_lints/src/methods/unnecessary_join.rs @@ -32,7 +32,7 @@ pub(super) fn check<'tcx>( UNNECESSARY_JOIN, span.with_hi(expr.span.hi()), r#"called `.collect::>().join("")` on an iterator"#, - "try using", + "consider using", "collect::()".to_owned(), applicability, ); diff --git a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs index 5ddedb24b15a4..4822970e47ef5 100644 --- a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs +++ b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation { ident.span, "non-standard lint formulation", None, - &format!("try using `{}` instead", formulation.correction), + &format!("consider using `{}`", formulation.correction), ); } return; From 38d95859780c4ddabff042b9b715ea292a3acfcf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 18 Jan 2024 18:17:53 +0100 Subject: [PATCH 153/676] Update ui tests --- tests/ui-internal/check_formulation.stderr | 4 +- tests/ui/join_absolute_paths.stderr | 8 +- tests/ui/manual_ok_or.stderr | 2 +- tests/ui/manual_saturating_arithmetic.stderr | 48 ++++++------ tests/ui/option_as_ref_deref.stderr | 36 ++++----- tests/ui/option_map_or_err_ok.stderr | 2 +- tests/ui/option_map_or_none.stderr | 10 +-- tests/ui/result_map_or_into_option.stderr | 6 +- tests/ui/same_item_push.stderr | 10 +-- tests/ui/single_char_pattern.stderr | 80 ++++++++++---------- tests/ui/unnecessary_join.stderr | 4 +- 11 files changed, 105 insertions(+), 105 deletions(-) diff --git a/tests/ui-internal/check_formulation.stderr b/tests/ui-internal/check_formulation.stderr index 96fa617601ff4..42a872d9a83f7 100644 --- a/tests/ui-internal/check_formulation.stderr +++ b/tests/ui-internal/check_formulation.stderr @@ -4,7 +4,7 @@ error: non-standard lint formulation LL | /// Check for lint formulations that are correct | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: try using `Checks for` instead + = help: consider using `Checks for` = note: `-D clippy::almost-standard-lint-formulation` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::almost_standard_lint_formulation)]` @@ -14,7 +14,7 @@ error: non-standard lint formulation LL | /// Detects uses of incorrect formulations | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: try using `Checks for` instead + = help: consider using `Checks for` error: aborting due to 2 previous errors diff --git a/tests/ui/join_absolute_paths.stderr b/tests/ui/join_absolute_paths.stderr index 0c2f89d9978b3..ab4d189ca3a22 100644 --- a/tests/ui/join_absolute_paths.stderr +++ b/tests/ui/join_absolute_paths.stderr @@ -11,7 +11,7 @@ help: if this is unintentional, try removing the starting separator | LL | path.join("sh"); | ~~~~ -help: if this is intentional, try using `Path::new` instead +help: if this is intentional, consider using `Path::new` | LL | PathBuf::from("/sh"); | ~~~~~~~~~~~~~~~~~~~~ @@ -27,7 +27,7 @@ help: if this is unintentional, try removing the starting separator | LL | path.join("\user"); | ~~~~~~~ -help: if this is intentional, try using `Path::new` instead +help: if this is intentional, consider using `Path::new` | LL | PathBuf::from("\\user"); | ~~~~~~~~~~~~~~~~~~~~~~~ @@ -43,7 +43,7 @@ help: if this is unintentional, try removing the starting separator | LL | path.join("sh"); | ~~~~ -help: if this is intentional, try using `Path::new` instead +help: if this is intentional, consider using `Path::new` | LL | PathBuf::from("/sh"); | ~~~~~~~~~~~~~~~~~~~~ @@ -59,7 +59,7 @@ help: if this is unintentional, try removing the starting separator | LL | path.join(r#"sh"#); | ~~~~~~~ -help: if this is intentional, try using `Path::new` instead +help: if this is intentional, consider using `Path::new` | LL | PathBuf::from(r#"/sh"#); | ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/manual_ok_or.stderr b/tests/ui/manual_ok_or.stderr index b277d22e59b63..89df6cdbedbcc 100644 --- a/tests/ui/manual_ok_or.stderr +++ b/tests/ui/manual_ok_or.stderr @@ -17,7 +17,7 @@ error: called `map_or(Err(_), Ok)` on an `Option` value --> $DIR/manual_ok_or.rs:14:5 | LL | foo.map_or(Err("error"), Ok); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok_or` instead: `foo.ok_or("error")` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok_or`: `foo.ok_or("error")` | = note: `-D clippy::option-map-or-err-ok` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::option_map_or_err_ok)]` diff --git a/tests/ui/manual_saturating_arithmetic.stderr b/tests/ui/manual_saturating_arithmetic.stderr index dc36a5ee7c692..3ce108b1ca81e 100644 --- a/tests/ui/manual_saturating_arithmetic.stderr +++ b/tests/ui/manual_saturating_arithmetic.stderr @@ -2,7 +2,7 @@ error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:6:13 | LL | let _ = 1u32.checked_add(1).unwrap_or(u32::max_value()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u32.saturating_add(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1u32.saturating_add(1)` | = note: `-D clippy::manual-saturating-arithmetic` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_saturating_arithmetic)]` @@ -11,13 +11,13 @@ error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:7:13 | LL | let _ = 1u32.checked_add(1).unwrap_or(u32::MAX); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u32.saturating_add(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1u32.saturating_add(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:8:13 | LL | let _ = 1u8.checked_add(1).unwrap_or(255); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u8.saturating_add(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1u8.saturating_add(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:9:13 @@ -26,49 +26,49 @@ LL | let _ = 1u128 | _____________^ LL | | .checked_add(1) LL | | .unwrap_or(340_282_366_920_938_463_463_374_607_431_768_211_455); - | |_______________________________________________________________________^ help: try using `saturating_add`: `1u128.saturating_add(1)` + | |_______________________________________________________________________^ help: consider using `saturating_add`: `1u128.saturating_add(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:14:13 | LL | let _ = 1u32.checked_mul(1).unwrap_or(u32::MAX); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_mul`: `1u32.saturating_mul(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_mul`: `1u32.saturating_mul(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:16:13 | LL | let _ = 1u32.checked_sub(1).unwrap_or(u32::min_value()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u32.saturating_sub(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u32.saturating_sub(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:17:13 | LL | let _ = 1u32.checked_sub(1).unwrap_or(u32::MIN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u32.saturating_sub(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u32.saturating_sub(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:18:13 | LL | let _ = 1u8.checked_sub(1).unwrap_or(0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u8.saturating_sub(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u8.saturating_sub(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:22:13 | LL | let _ = 1i32.checked_add(1).unwrap_or(i32::max_value()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:23:13 | LL | let _ = 1i32.checked_add(1).unwrap_or(i32::MAX); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:24:13 | LL | let _ = 1i8.checked_add(1).unwrap_or(127); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i8.saturating_add(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i8.saturating_add(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:25:13 @@ -77,25 +77,25 @@ LL | let _ = 1i128 | _____________^ LL | | .checked_add(1) LL | | .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727); - | |_______________________________________________________________________^ help: try using `saturating_add`: `1i128.saturating_add(1)` + | |_______________________________________________________________________^ help: consider using `saturating_add`: `1i128.saturating_add(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:28:13 | LL | let _ = 1i32.checked_add(-1).unwrap_or(i32::min_value()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(-1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(-1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:29:13 | LL | let _ = 1i32.checked_add(-1).unwrap_or(i32::MIN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(-1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(-1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:30:13 | LL | let _ = 1i8.checked_add(-1).unwrap_or(-128); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i8.saturating_add(-1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i8.saturating_add(-1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:31:13 @@ -104,25 +104,25 @@ LL | let _ = 1i128 | _____________^ LL | | .checked_add(-1) LL | | .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728); - | |________________________________________________________________________^ help: try using `saturating_add`: `1i128.saturating_add(-1)` + | |________________________________________________________________________^ help: consider using `saturating_add`: `1i128.saturating_add(-1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:38:13 | LL | let _ = 1i32.checked_sub(1).unwrap_or(i32::min_value()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:39:13 | LL | let _ = 1i32.checked_sub(1).unwrap_or(i32::MIN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:40:13 | LL | let _ = 1i8.checked_sub(1).unwrap_or(-128); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i8.saturating_sub(1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i8.saturating_sub(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:41:13 @@ -131,25 +131,25 @@ LL | let _ = 1i128 | _____________^ LL | | .checked_sub(1) LL | | .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728); - | |________________________________________________________________________^ help: try using `saturating_sub`: `1i128.saturating_sub(1)` + | |________________________________________________________________________^ help: consider using `saturating_sub`: `1i128.saturating_sub(1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:44:13 | LL | let _ = 1i32.checked_sub(-1).unwrap_or(i32::max_value()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(-1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(-1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:45:13 | LL | let _ = 1i32.checked_sub(-1).unwrap_or(i32::MAX); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(-1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(-1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:46:13 | LL | let _ = 1i8.checked_sub(-1).unwrap_or(127); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i8.saturating_sub(-1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i8.saturating_sub(-1)` error: manual saturating arithmetic --> $DIR/manual_saturating_arithmetic.rs:47:13 @@ -158,7 +158,7 @@ LL | let _ = 1i128 | _____________^ LL | | .checked_sub(-1) LL | | .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727); - | |_______________________________________________________________________^ help: try using `saturating_sub`: `1i128.saturating_sub(-1)` + | |_______________________________________________________________________^ help: consider using `saturating_sub`: `1i128.saturating_sub(-1)` error: aborting due to 24 previous errors diff --git a/tests/ui/option_as_ref_deref.stderr b/tests/ui/option_as_ref_deref.stderr index 9d173e409abcc..036b8c749e417 100644 --- a/tests/ui/option_as_ref_deref.stderr +++ b/tests/ui/option_as_ref_deref.stderr @@ -2,7 +2,7 @@ error: called `.as_ref().map(Deref::deref)` on an `Option` value --> $DIR/option_as_ref_deref.rs:11:13 | LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.clone().as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.clone().as_deref()` | = note: `-D clippy::option-as-ref-deref` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::option_as_ref_deref)]` @@ -15,103 +15,103 @@ LL | let _ = opt.clone() LL | | .as_ref().map( LL | | Deref::deref LL | | ) - | |_________^ help: try using as_deref instead: `opt.clone().as_deref()` + | |_________^ help: consider using as_deref: `opt.clone().as_deref()` error: called `.as_mut().map(DerefMut::deref_mut)` on an `Option` value --> $DIR/option_as_ref_deref.rs:20:13 | LL | let _ = opt.as_mut().map(DerefMut::deref_mut); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()` error: called `.as_ref().map(String::as_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:22:13 | LL | let _ = opt.as_ref().map(String::as_str); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_ref().map(|x| x.as_str())` on an `Option` value --> $DIR/option_as_ref_deref.rs:23:13 | LL | let _ = opt.as_ref().map(|x| x.as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_mut().map(String::as_mut_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:24:13 | LL | let _ = opt.as_mut().map(String::as_mut_str); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()` error: called `.as_mut().map(|x| x.as_mut_str())` on an `Option` value --> $DIR/option_as_ref_deref.rs:25:13 | LL | let _ = opt.as_mut().map(|x| x.as_mut_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()` error: called `.as_ref().map(CString::as_c_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:26:13 | LL | let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(CString::new(vec![]).unwrap()).as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(CString::new(vec![]).unwrap()).as_deref()` error: called `.as_ref().map(OsString::as_os_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:27:13 | LL | let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(OsString::new()).as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(OsString::new()).as_deref()` error: called `.as_ref().map(PathBuf::as_path)` on an `Option` value --> $DIR/option_as_ref_deref.rs:28:13 | LL | let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(PathBuf::new()).as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(PathBuf::new()).as_deref()` error: called `.as_ref().map(Vec::as_slice)` on an `Option` value --> $DIR/option_as_ref_deref.rs:29:13 | LL | let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(Vec::<()>::new()).as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(Vec::<()>::new()).as_deref()` error: called `.as_mut().map(Vec::as_mut_slice)` on an `Option` value --> $DIR/option_as_ref_deref.rs:30:13 | LL | let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `Some(Vec::<()>::new()).as_deref_mut()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `Some(Vec::<()>::new()).as_deref_mut()` error: called `.as_ref().map(|x| x.deref())` on an `Option` value --> $DIR/option_as_ref_deref.rs:32:13 | LL | let _ = opt.as_ref().map(|x| x.deref()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_mut().map(|x| x.deref_mut())` on an `Option` value --> $DIR/option_as_ref_deref.rs:33:13 | LL | let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.clone().as_deref_mut()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.clone().as_deref_mut()` error: called `.as_ref().map(|x| &**x)` on an `Option` value --> $DIR/option_as_ref_deref.rs:40:13 | LL | let _ = opt.as_ref().map(|x| &**x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_mut().map(|x| &mut **x)` on an `Option` value --> $DIR/option_as_ref_deref.rs:41:13 | LL | let _ = opt.as_mut().map(|x| &mut **x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()` error: called `.as_ref().map(std::ops::Deref::deref)` on an `Option` value --> $DIR/option_as_ref_deref.rs:44:13 | LL | let _ = opt.as_ref().map(std::ops::Deref::deref); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_ref().map(String::as_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:56:13 | LL | let _ = opt.as_ref().map(String::as_str); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: aborting due to 18 previous errors diff --git a/tests/ui/option_map_or_err_ok.stderr b/tests/ui/option_map_or_err_ok.stderr index a193e3c4c49d3..381601cb6b3aa 100644 --- a/tests/ui/option_map_or_err_ok.stderr +++ b/tests/ui/option_map_or_err_ok.stderr @@ -2,7 +2,7 @@ error: called `map_or(Err(_), Ok)` on an `Option` value --> $DIR/option_map_or_err_ok.rs:5:13 | LL | let _ = x.map_or(Err("a"), Ok); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok_or` instead: `x.ok_or("a")` + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok_or`: `x.ok_or("a")` | = note: `-D clippy::option-map-or-err-ok` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::option_map_or_err_ok)]` diff --git a/tests/ui/option_map_or_none.stderr b/tests/ui/option_map_or_none.stderr index f2cfc3f9a2815..d58ff83c3da27 100644 --- a/tests/ui/option_map_or_none.stderr +++ b/tests/ui/option_map_or_none.stderr @@ -2,7 +2,7 @@ error: called `map_or(None, ..)` on an `Option` value --> $DIR/option_map_or_none.rs:10:26 | LL | let _: Option = opt.map_or(None, |x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `map` instead: `opt.map(|x| x + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `map`: `opt.map(|x| x + 1)` | = note: `-D clippy::option-map-or-none` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::option_map_or_none)]` @@ -14,13 +14,13 @@ LL | let _: Option = opt.map_or(None, |x| { | __________________________^ LL | | Some(x + 1) LL | | }); - | |_________________________^ help: try using `map` instead: `opt.map(|x| x + 1)` + | |_________________________^ help: consider using `map`: `opt.map(|x| x + 1)` error: called `map_or(None, ..)` on an `Option` value --> $DIR/option_map_or_none.rs:17:26 | LL | let _: Option = opt.map_or(None, bar); - | ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `opt.and_then(bar)` + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `and_then`: `opt.and_then(bar)` error: called `map_or(None, ..)` on an `Option` value --> $DIR/option_map_or_none.rs:18:26 @@ -33,7 +33,7 @@ LL | | Some(offset + height) LL | | }); | |______^ | -help: try using `and_then` instead +help: consider using `and_then` | LL ~ let _: Option = opt.and_then(|x| { LL + let offset = 0; @@ -46,7 +46,7 @@ error: called `map_or(None, Some)` on a `Result` value --> $DIR/option_map_or_none.rs:25:26 | LL | let _: Option = r.map_or(None, Some); - | ^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `r.ok()` + | ^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `r.ok()` | = note: `-D clippy::result-map-or-into-option` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::result_map_or_into_option)]` diff --git a/tests/ui/result_map_or_into_option.stderr b/tests/ui/result_map_or_into_option.stderr index 3d6bfef48ecab..201868f09efa6 100644 --- a/tests/ui/result_map_or_into_option.stderr +++ b/tests/ui/result_map_or_into_option.stderr @@ -2,7 +2,7 @@ error: called `map_or(None, Some)` on a `Result` value --> $DIR/result_map_or_into_option.rs:5:13 | LL | let _ = opt.map_or(None, Some); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `opt.ok()` | = note: `-D clippy::result-map-or-into-option` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::result_map_or_into_option)]` @@ -11,13 +11,13 @@ error: called `map_or_else(|_| None, Some)` on a `Result` value --> $DIR/result_map_or_into_option.rs:7:13 | LL | let _ = opt.map_or_else(|_| None, Some); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `opt.ok()` error: called `map_or_else(|_| None, Some)` on a `Result` value --> $DIR/result_map_or_into_option.rs:10:13 | LL | let _ = opt.map_or_else(|_| { None }, Some); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `opt.ok()` error: aborting due to 3 previous errors diff --git a/tests/ui/same_item_push.stderr b/tests/ui/same_item_push.stderr index f519be463695b..f569aab64900a 100644 --- a/tests/ui/same_item_push.stderr +++ b/tests/ui/same_item_push.stderr @@ -4,7 +4,7 @@ error: it looks like the same item is being pushed into this Vec LL | vec.push(item); | ^^^ | - = help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item) + = help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item) = note: `-D clippy::same-item-push` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::same_item_push)]` @@ -14,7 +14,7 @@ error: it looks like the same item is being pushed into this Vec LL | vec.push(item); | ^^^ | - = help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item) + = help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item) error: it looks like the same item is being pushed into this Vec --> $DIR/same_item_push.rs:36:9 @@ -22,7 +22,7 @@ error: it looks like the same item is being pushed into this Vec LL | vec.push(13); | ^^^ | - = help: try using vec![13;SIZE] or vec.resize(NEW_SIZE, 13) + = help: consider using vec![13;SIZE] or vec.resize(NEW_SIZE, 13) error: it looks like the same item is being pushed into this Vec --> $DIR/same_item_push.rs:42:9 @@ -30,7 +30,7 @@ error: it looks like the same item is being pushed into this Vec LL | vec.push(VALUE); | ^^^ | - = help: try using vec![VALUE;SIZE] or vec.resize(NEW_SIZE, VALUE) + = help: consider using vec![VALUE;SIZE] or vec.resize(NEW_SIZE, VALUE) error: it looks like the same item is being pushed into this Vec --> $DIR/same_item_push.rs:49:9 @@ -38,7 +38,7 @@ error: it looks like the same item is being pushed into this Vec LL | vec.push(item); | ^^^ | - = help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item) + = help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item) error: aborting due to 5 previous errors diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 781ab316d9de3..664d6b5a1e9b0 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -2,7 +2,7 @@ error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:7:13 | LL | x.split("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` | = note: `-D clippy::single-char-pattern` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::single_char_pattern)]` @@ -11,235 +11,235 @@ error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:13:13 | LL | x.split("ß"); - | ^^^ help: try using a `char` instead: `'ß'` + | ^^^ help: consider using a `char`: `'ß'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:14:13 | LL | x.split("ℝ"); - | ^^^ help: try using a `char` instead: `'ℝ'` + | ^^^ help: consider using a `char`: `'ℝ'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:15:13 | LL | x.split("💣"); - | ^^^^ help: try using a `char` instead: `'💣'` + | ^^^^ help: consider using a `char`: `'💣'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:18:23 | LL | x.split_inclusive("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:19:16 | LL | x.contains("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:20:19 | LL | x.starts_with("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:21:17 | LL | x.ends_with("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:22:12 | LL | x.find("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:23:13 | LL | x.rfind("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:24:14 | LL | x.rsplit("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:25:24 | LL | x.split_terminator("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:26:25 | LL | x.rsplit_terminator("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:27:17 | LL | x.splitn(2, "x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:28:18 | LL | x.rsplitn(2, "x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:29:18 | LL | x.split_once("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:30:19 | LL | x.rsplit_once("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:31:15 | LL | x.matches("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:32:16 | LL | x.rmatches("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:33:21 | LL | x.match_indices("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:34:22 | LL | x.rmatch_indices("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:35:26 | LL | x.trim_start_matches("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:36:24 | LL | x.trim_end_matches("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:37:20 | LL | x.strip_prefix("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:38:20 | LL | x.strip_suffix("x"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:39:15 | LL | x.replace("x", "y"); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:40:16 | LL | x.replacen("x", "y", 3); - | ^^^ help: try using a `char` instead: `'x'` + | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:42:13 | LL | x.split("\n"); - | ^^^^ help: try using a `char` instead: `'\n'` + | ^^^^ help: consider using a `char`: `'\n'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:43:13 | LL | x.split("'"); - | ^^^ help: try using a `char` instead: `'\''` + | ^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:44:13 | LL | x.split("\'"); - | ^^^^ help: try using a `char` instead: `'\''` + | ^^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:46:13 | LL | x.split("\""); - | ^^^^ help: try using a `char` instead: `'"'` + | ^^^^ help: consider using a `char`: `'"'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:51:31 | LL | x.replace(';', ",").split(","); // issue #2978 - | ^^^ help: try using a `char` instead: `','` + | ^^^ help: consider using a `char`: `','` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:52:19 | LL | x.starts_with("\x03"); // issue #2996 - | ^^^^^^ help: try using a `char` instead: `'\x03'` + | ^^^^^^ help: consider using a `char`: `'\x03'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:59:13 | LL | x.split(r"a"); - | ^^^^ help: try using a `char` instead: `'a'` + | ^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:60:13 | LL | x.split(r#"a"#); - | ^^^^^^ help: try using a `char` instead: `'a'` + | ^^^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:61:13 | LL | x.split(r###"a"###); - | ^^^^^^^^^^ help: try using a `char` instead: `'a'` + | ^^^^^^^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:62:13 | LL | x.split(r###"'"###); - | ^^^^^^^^^^ help: try using a `char` instead: `'\''` + | ^^^^^^^^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:63:13 | LL | x.split(r###"#"###); - | ^^^^^^^^^^ help: try using a `char` instead: `'#'` + | ^^^^^^^^^^ help: consider using a `char`: `'#'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:65:13 | LL | x.split(r#"\"#); - | ^^^^^^ help: try using a `char` instead: `'\\'` + | ^^^^^^ help: consider using a `char`: `'\\'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:66:13 | LL | x.split(r"\"); - | ^^^^ help: try using a `char` instead: `'\\'` + | ^^^^ help: consider using a `char`: `'\\'` error: aborting due to 40 previous errors diff --git a/tests/ui/unnecessary_join.stderr b/tests/ui/unnecessary_join.stderr index 8bf2ac5fdb1d9..205a714b694ae 100644 --- a/tests/ui/unnecessary_join.stderr +++ b/tests/ui/unnecessary_join.stderr @@ -4,7 +4,7 @@ error: called `.collect::>().join("")` on an iterator LL | .collect::>() | __________^ LL | | .join(""); - | |_________________^ help: try using: `collect::()` + | |_________________^ help: consider using: `collect::()` | = note: `-D clippy::unnecessary-join` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_join)]` @@ -15,7 +15,7 @@ error: called `.collect::>().join("")` on an iterator LL | .collect::>() | __________^ LL | | .join(""); - | |_________________^ help: try using: `collect::()` + | |_________________^ help: consider using: `collect::()` error: aborting due to 2 previous errors From fd6e752f4e4fef715144b360fb7e29b4f3d10df9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 20 Jan 2024 16:57:43 +0100 Subject: [PATCH 154/676] Move `has_non_exhaustive_attr` function into `clippy_utils` --- clippy_lints/src/derive.rs | 19 ++++--------------- clippy_utils/src/attrs.rs | 12 ++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index aab2550ba6eb0..081cbcb770fb5 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy}; -use clippy_utils::{is_lint_allowed, match_def_path, paths}; +use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths}; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor}; @@ -11,8 +11,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, AdtDef, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, - Ty, TyCtxt, + self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, Ty, + TyCtxt, }; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; @@ -442,17 +442,6 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { } } -fn has_non_exhaustive_attr(cx: &LateContext<'_>, adt: AdtDef<'_>) -> bool { - adt.is_variant_list_non_exhaustive() - || cx.tcx.has_attr(adt.did(), sym::non_exhaustive) - || adt.variants().iter().any(|variant_def| { - variant_def.is_field_list_non_exhaustive() || cx.tcx.has_attr(variant_def.def_id, sym::non_exhaustive) - }) - || adt - .all_fields() - .any(|field_def| cx.tcx.has_attr(field_def.did, sym::non_exhaustive)) -} - /// Implementation of the `DERIVE_PARTIAL_EQ_WITHOUT_EQ` lint. fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) { if let ty::Adt(adt, args) = ty.kind() @@ -460,7 +449,7 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq) && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) - && !has_non_exhaustive_attr(cx, *adt) + && !has_non_exhaustive_attr(cx.tcx, *adt) && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[]) // If all of our fields implement `Eq`, we can implement `Eq` too diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index ad8619f0d3d96..2d0c2cf125364 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -1,5 +1,6 @@ use rustc_ast::{ast, attr}; use rustc_errors::Applicability; +use rustc_middle::ty::{AdtDef, TyCtxt}; use rustc_session::Session; use rustc_span::sym; use std::str::FromStr; @@ -159,3 +160,14 @@ pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool { .filter_map(ast::Attribute::meta_item_list) .any(|l| attr::list_contains_name(&l, sym::hidden)) } + +pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool { + adt.is_variant_list_non_exhaustive() + || tcx.has_attr(adt.did(), sym::non_exhaustive) + || adt.variants().iter().any(|variant_def| { + variant_def.is_field_list_non_exhaustive() || tcx.has_attr(variant_def.def_id, sym::non_exhaustive) + }) + || adt + .all_fields() + .any(|field_def| tcx.has_attr(field_def.did, sym::non_exhaustive)) +} From edba94907d2f84f35f8e5673a363bf2d42e1c29a Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sat, 20 Jan 2024 08:09:14 -0800 Subject: [PATCH 155/676] 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 156/676] 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 f73879e096301b921cc763c15f7020ff72736988 Mon Sep 17 00:00:00 2001 From: Quinn Sinclair Date: Thu, 21 Dec 2023 13:26:46 +0200 Subject: [PATCH 157/676] `unused_io_amount` captures `Ok(_)`s Partial rewrite of `unused_io_account` to lint over Ok(_). Moved the check to `check_block` to simplify context checking for expressions and allow us to check only some expressions. For match (expr, arms) we emit a lint for io ops used on `expr` when an arm is `Ok(_)`. Also considers the cases when there are guards in the arms. It also captures `if let Ok(_) = ...` cases. For `Ok(_)` it emits a note indicating where the value is ignored. changelog: False Negatives [`unused_io_amount`]: Extended `unused_io_amount` to catch `Ok(_)`s in `If let` and match exprs. --- clippy_lints/src/unused_io_amount.rs | 292 ++++++++++++++++++--------- tests/ui/unused_io_amount.rs | 87 ++++++++ tests/ui/unused_io_amount.stderr | 141 +++++++++++-- 3 files changed, 400 insertions(+), 120 deletions(-) diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index 1de9adfcb963a..adc66e15ff501 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -1,9 +1,10 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; -use clippy_utils::{is_trait_method, is_try, match_trait_method, paths}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{is_res_lang_ctor, is_trait_method, match_trait_method, paths}; +use hir::{ExprKind, PatKind}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::sym; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does @@ -45,126 +46,219 @@ declare_clippy_lint! { declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]); +#[derive(Copy, Clone)] +enum IoOp { + AsyncWrite(bool), + AsyncRead(bool), + SyncRead(bool), + SyncWrite(bool), +} + impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { - fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { - let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = s.kind else { - return; - }; + /// We perform the check on the block level. + /// If we want to catch match and if expressions that act as returns of the block + /// we need to check them at `check_expr` or `check_block` as they are not stmts + /// but we can't check them at `check_expr` because we need the broader context + /// because we should do this only for the final expression of the block, and not for + /// `StmtKind::Local` which binds values => the io amount is used. + /// + /// To check for unused io amount in stmts, we only consider `StmtKind::Semi`. + /// `StmtKind::Local` is not considered because it binds values => the io amount is used. + /// `StmtKind::Expr` is not considered because requires unit type => the io amount is used. + /// `StmtKind::Item` is not considered because it's not an expression. + /// + /// We then check the individual expressions via `check_expr`. We use the same logic for + /// semi expressions and the final expression as we need to check match and if expressions + /// for binding of the io amount to `Ok(_)`. + /// + /// We explicitly check for the match source to be Normal as it needs special logic + /// to consider the arms, and we want to avoid breaking the logic for situations where things + /// get desugared to match. + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'tcx>) { + for stmt in block.stmts { + if let hir::StmtKind::Semi(exp) = stmt.kind { + check_expr(cx, exp); + } + } - match expr.kind { - hir::ExprKind::Match(res, _, _) if is_try(cx, expr).is_some() => { - if let hir::ExprKind::Call(func, [ref arg_0, ..]) = res.kind { - if matches!( - func.kind, - hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..)) - ) { - check_map_error(cx, arg_0, expr); + if let Some(exp) = block.expr + && matches!(exp.kind, hir::ExprKind::If(_, _, _) | hir::ExprKind::Match(_, _, _)) + { + check_expr(cx, exp); + } + } +} + +fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { + match expr.kind { + hir::ExprKind::If(cond, _, _) + if let ExprKind::Let(hir::Let { pat, init, .. }) = cond.kind + && pattern_is_ignored_ok(cx, pat) + && let Some(op) = should_lint(cx, init) => + { + emit_lint(cx, cond.span, op, &[pat.span]); + }, + hir::ExprKind::Match(expr, arms, hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => { + let found_arms: Vec<_> = arms + .iter() + .filter_map(|arm| { + if pattern_is_ignored_ok(cx, arm.pat) { + Some(arm.span) + } else { + None } - } else { - check_map_error(cx, res, expr); - } - }, - hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() { - "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" | "is_ok" | "is_err" => { - check_map_error(cx, arg_0, expr); - }, - _ => (), - }, - _ => (), + }) + .collect(); + if !found_arms.is_empty() { + emit_lint(cx, expr.span, op, found_arms.as_slice()); + } + }, + _ if let Some(op) = should_lint(cx, expr) => { + emit_lint(cx, expr.span, op, &[]); + }, + _ => {}, + }; +} + +fn should_lint<'a>(cx: &LateContext<'a>, mut inner: &'a hir::Expr<'a>) -> Option { + inner = unpack_match(inner); + inner = unpack_try(inner); + inner = unpack_call_chain(inner); + inner = unpack_await(inner); + // we type-check it to get whether it's a read/write or their vectorized forms + // and keep only the ones that are produce io amount + check_io_mode(cx, inner) +} + +fn pattern_is_ignored_ok(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> bool { + // the if checks whether we are in a result Ok( ) pattern + // and the return checks whether it is unhandled + + if let PatKind::TupleStruct(ref path, inner_pat, ddp) = pat.kind + // we check against Result::Ok to avoid linting on Err(_) or something else. + && is_res_lang_ctor(cx, cx.qpath_res(path, pat.hir_id), hir::LangItem::ResultOk) + { + return match (inner_pat, ddp.as_opt_usize()) { + // Ok(_) pattern + ([inner_pat], None) if matches!(inner_pat.kind, PatKind::Wild) => true, + // Ok(..) pattern + ([], Some(0)) => true, + _ => false, + }; + } + false +} + +fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { + while let hir::ExprKind::MethodCall(path, receiver, ..) = expr.kind { + if matches!( + path.ident.as_str(), + "unwrap" | "expect" | "unwrap_or" | "unwrap_or_else" | "ok" | "is_ok" | "is_err" | "or_else" | "or" + ) { + expr = receiver; + } else { + break; } } + expr +} + +fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { + while let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind + && matches!( + func.kind, + hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..)) + ) + { + expr = arg_0; + } + expr +} + +fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { + while let hir::ExprKind::Match(res, _, _) = expr.kind { + expr = res; + } + expr } /// If `expr` is an (e).await, return the inner expression "e" that's being /// waited on. Otherwise return None. -fn try_remove_await<'a>(expr: &'a hir::Expr<'a>) -> Option<&hir::Expr<'a>> { +fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> { if let hir::ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind { if let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind { if matches!( func.kind, hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..)) ) { - return Some(arg_0); + return arg_0; } } } - - None + expr } -fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) { - let mut call = call; - while let hir::ExprKind::MethodCall(path, receiver, ..) = call.kind { - if matches!(path.ident.as_str(), "or" | "or_else" | "ok") { - call = receiver; - } else { - break; - } - } +/// Check whether the current expr is a function call for an IO operation +fn check_io_mode(cx: &LateContext<'_>, call: &hir::Expr<'_>) -> Option { + let hir::ExprKind::MethodCall(path, ..) = call.kind else { + return None; + }; - if let Some(call) = try_remove_await(call) { - check_method_call(cx, call, expr, true); - } else { - check_method_call(cx, call, expr, false); + let vectorized = match path.ident.as_str() { + "write_vectored" | "read_vectored" => true, + "write" | "read" => false, + _ => { + return None; + }, + }; + + match ( + is_trait_method(cx, call, sym::IoRead), + is_trait_method(cx, call, sym::IoWrite), + match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT) + || match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCREADEXT), + match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCWRITEEXT) + || match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCWRITEEXT), + ) { + (true, _, _, _) => Some(IoOp::SyncRead(vectorized)), + (_, true, _, _) => Some(IoOp::SyncWrite(vectorized)), + (_, _, true, _) => Some(IoOp::AsyncRead(vectorized)), + (_, _, _, true) => Some(IoOp::AsyncWrite(vectorized)), + _ => None, } } -fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>, is_await: bool) { - if let hir::ExprKind::MethodCall(path, ..) = call.kind { - let symbol = path.ident.as_str(); - let read_trait = if is_await { - match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT) - || match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCREADEXT) - } else { - is_trait_method(cx, call, sym::IoRead) - }; - let write_trait = if is_await { - match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCWRITEEXT) - || match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCWRITEEXT) - } else { - is_trait_method(cx, call, sym::IoWrite) - }; +fn emit_lint(cx: &LateContext<'_>, span: Span, op: IoOp, wild_cards: &[Span]) { + let (msg, help) = match op { + IoOp::AsyncRead(false) => ( + "read amount is not handled", + Some("use `AsyncReadExt::read_exact` instead, or handle partial reads"), + ), + IoOp::SyncRead(false) => ( + "read amount is not handled", + Some("use `Read::read_exact` instead, or handle partial reads"), + ), + IoOp::SyncWrite(false) => ( + "written amount is not handled", + Some("use `Write::write_all` instead, or handle partial writes"), + ), + IoOp::AsyncWrite(false) => ( + "written amount is not handled", + Some("use `AsyncWriteExt::write_all` instead, or handle partial writes"), + ), + IoOp::SyncRead(true) | IoOp::AsyncRead(true) => ("read amount is not handled", None), + IoOp::SyncWrite(true) | IoOp::AsyncWrite(true) => ("written amount is not handled", None), + }; - match (read_trait, write_trait, symbol, is_await) { - (true, _, "read", false) => span_lint_and_help( - cx, - UNUSED_IO_AMOUNT, - expr.span, - "read amount is not handled", - None, - "use `Read::read_exact` instead, or handle partial reads", - ), - (true, _, "read", true) => span_lint_and_help( - cx, - UNUSED_IO_AMOUNT, - expr.span, - "read amount is not handled", - None, - "use `AsyncReadExt::read_exact` instead, or handle partial reads", - ), - (true, _, "read_vectored", _) => { - span_lint(cx, UNUSED_IO_AMOUNT, expr.span, "read amount is not handled"); - }, - (_, true, "write", false) => span_lint_and_help( - cx, - UNUSED_IO_AMOUNT, - expr.span, - "written amount is not handled", - None, - "use `Write::write_all` instead, or handle partial writes", - ), - (_, true, "write", true) => span_lint_and_help( - cx, - UNUSED_IO_AMOUNT, - expr.span, - "written amount is not handled", - None, - "use `AsyncWriteExt::write_all` instead, or handle partial writes", - ), - (_, true, "write_vectored", _) => { - span_lint(cx, UNUSED_IO_AMOUNT, expr.span, "written amount is not handled"); - }, - _ => (), + span_lint_and_then(cx, UNUSED_IO_AMOUNT, span, msg, |diag| { + if let Some(help_str) = help { + diag.help(help_str); } - } + for span in wild_cards { + diag.span_note( + *span, + "the result is consumed here, but the amount of I/O bytes remains unhandled", + ); + } + }); } diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 62aec6e9eafca..9974600dad5be 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -1,4 +1,5 @@ #![allow(dead_code, clippy::needless_pass_by_ref_mut)] +#![allow(clippy::redundant_pattern_matching)] #![warn(clippy::unused_io_amount)] extern crate futures; @@ -142,4 +143,90 @@ async fn undetected_bad_async_write(w: &mut W) { future.await.unwrap(); } +fn match_okay_underscore(s: &mut T) { + match s.write(b"test") { + //~^ ERROR: written amount is not handled + Ok(_) => todo!(), + //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled + Err(_) => todo!(), + }; + + let mut buf = [0u8; 4]; + match s.read(&mut buf) { + //~^ ERROR: read amount is not handled + Ok(_) => todo!(), + //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled + Err(_) => todo!(), + } +} + +fn match_okay_underscore_read_expr(s: &mut T) { + match s.read(&mut [0u8; 4]) { + //~^ ERROR: read amount is not handled + Ok(_) => todo!(), + //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled + Err(_) => todo!(), + } +} + +fn match_okay_underscore_write_expr(s: &mut T) { + match s.write(b"test") { + //~^ ERROR: written amount is not handled + Ok(_) => todo!(), + //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled + Err(_) => todo!(), + } +} + +fn returned_value_should_not_lint(s: &mut T) -> Result { + s.write(b"test") +} + +fn if_okay_underscore_read_expr(s: &mut T) { + if let Ok(_) = s.read(&mut [0u8; 4]) { + //~^ ERROR: read amount is not handled + todo!() + } +} + +fn if_okay_underscore_write_expr(s: &mut T) { + if let Ok(_) = s.write(b"test") { + //~^ ERROR: written amount is not handled + todo!() + } +} + +fn if_okay_dots_write_expr(s: &mut T) { + if let Ok(..) = s.write(b"test") { + //~^ ERROR: written amount is not handled + todo!() + } +} + +fn if_okay_underscore_write_expr_true_negative(s: &mut T) { + if let Ok(bound) = s.write(b"test") { + todo!() + } +} + +fn match_okay_underscore_true_neg(s: &mut T) { + match s.write(b"test") { + Ok(bound) => todo!(), + Err(_) => todo!(), + }; +} + +fn true_negative(s: &mut T) { + let mut buf = [0u8; 4]; + let read_amount = s.read(&mut buf).unwrap(); +} + +fn on_return_should_not_raise(s: &mut T) -> io::Result { + /// this is bad code because it goes around the problem of handling the read amount + /// by returning it, which makes it impossible to know this is a resonpose from the + /// correct account. + let mut buf = [0u8; 4]; + s.read(&mut buf) +} + fn main() {} diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index f9aef596a1c98..4af56d264bfa1 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -1,5 +1,5 @@ error: written amount is not handled - --> $DIR/unused_io_amount.rs:9:5 + --> $DIR/unused_io_amount.rs:10:5 | LL | s.write(b"test")?; | ^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | s.write(b"test")?; = help: to override `-D warnings` add `#[allow(clippy::unused_io_amount)]` error: read amount is not handled - --> $DIR/unused_io_amount.rs:12:5 + --> $DIR/unused_io_amount.rs:13:5 | LL | s.read(&mut buf)?; | ^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | s.read(&mut buf)?; = help: use `Read::read_exact` instead, or handle partial reads error: written amount is not handled - --> $DIR/unused_io_amount.rs:18:5 + --> $DIR/unused_io_amount.rs:19:5 | LL | s.write(b"test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | s.write(b"test").unwrap(); = help: use `Write::write_all` instead, or handle partial writes error: read amount is not handled - --> $DIR/unused_io_amount.rs:21:5 + --> $DIR/unused_io_amount.rs:22:5 | LL | s.read(&mut buf).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,19 +33,19 @@ LL | s.read(&mut buf).unwrap(); = help: use `Read::read_exact` instead, or handle partial reads error: read amount is not handled - --> $DIR/unused_io_amount.rs:26:5 + --> $DIR/unused_io_amount.rs:27:5 | LL | s.read_vectored(&mut [io::IoSliceMut::new(&mut [])])?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: written amount is not handled - --> $DIR/unused_io_amount.rs:28:5 + --> $DIR/unused_io_amount.rs:29:5 | LL | s.write_vectored(&[io::IoSlice::new(&[])])?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: read amount is not handled - --> $DIR/unused_io_amount.rs:36:5 + --> $DIR/unused_io_amount.rs:37:5 | LL | reader.read(&mut result).ok()?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | reader.read(&mut result).ok()?; = help: use `Read::read_exact` instead, or handle partial reads error: read amount is not handled - --> $DIR/unused_io_amount.rs:46:5 + --> $DIR/unused_io_amount.rs:47:5 | LL | reader.read(&mut result).or_else(|err| Err(err))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | reader.read(&mut result).or_else(|err| Err(err))?; = help: use `Read::read_exact` instead, or handle partial reads error: read amount is not handled - --> $DIR/unused_io_amount.rs:59:5 + --> $DIR/unused_io_amount.rs:60:5 | LL | reader.read(&mut result).or(Err(Error::Kind))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | reader.read(&mut result).or(Err(Error::Kind))?; = help: use `Read::read_exact` instead, or handle partial reads error: read amount is not handled - --> $DIR/unused_io_amount.rs:67:5 + --> $DIR/unused_io_amount.rs:68:5 | LL | / reader LL | | @@ -82,7 +82,7 @@ LL | | .expect("error"); = help: use `Read::read_exact` instead, or handle partial reads error: written amount is not handled - --> $DIR/unused_io_amount.rs:77:5 + --> $DIR/unused_io_amount.rs:78:5 | LL | s.write(b"ok").is_ok(); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | s.write(b"ok").is_ok(); = help: use `Write::write_all` instead, or handle partial writes error: written amount is not handled - --> $DIR/unused_io_amount.rs:79:5 + --> $DIR/unused_io_amount.rs:80:5 | LL | s.write(b"err").is_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +98,7 @@ LL | s.write(b"err").is_err(); = help: use `Write::write_all` instead, or handle partial writes error: read amount is not handled - --> $DIR/unused_io_amount.rs:82:5 + --> $DIR/unused_io_amount.rs:83:5 | LL | s.read(&mut buf).is_ok(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL | s.read(&mut buf).is_ok(); = help: use `Read::read_exact` instead, or handle partial reads error: read amount is not handled - --> $DIR/unused_io_amount.rs:84:5 + --> $DIR/unused_io_amount.rs:85:5 | LL | s.read(&mut buf).is_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -114,7 +114,7 @@ LL | s.read(&mut buf).is_err(); = help: use `Read::read_exact` instead, or handle partial reads error: written amount is not handled - --> $DIR/unused_io_amount.rs:89:5 + --> $DIR/unused_io_amount.rs:90:5 | LL | w.write(b"hello world").await.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | w.write(b"hello world").await.unwrap(); = help: use `AsyncWriteExt::write_all` instead, or handle partial writes error: read amount is not handled - --> $DIR/unused_io_amount.rs:95:5 + --> $DIR/unused_io_amount.rs:96:5 | LL | r.read(&mut buf[..]).await.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,7 +130,15 @@ LL | r.read(&mut buf[..]).await.unwrap(); = help: use `AsyncReadExt::read_exact` instead, or handle partial reads error: written amount is not handled - --> $DIR/unused_io_amount.rs:109:9 + --> $DIR/unused_io_amount.rs:104:5 + | +LL | w.write(b"hello world"); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `AsyncWriteExt::write_all` instead, or handle partial writes + +error: written amount is not handled + --> $DIR/unused_io_amount.rs:110:9 | LL | w.write(b"hello world").await?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,7 +146,7 @@ LL | w.write(b"hello world").await?; = help: use `AsyncWriteExt::write_all` instead, or handle partial writes error: read amount is not handled - --> $DIR/unused_io_amount.rs:118:9 + --> $DIR/unused_io_amount.rs:119:9 | LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,7 +154,7 @@ LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?; = help: use `AsyncReadExt::read_exact` instead, or handle partial reads error: written amount is not handled - --> $DIR/unused_io_amount.rs:127:5 + --> $DIR/unused_io_amount.rs:128:5 | LL | w.write(b"hello world").await.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,12 +162,103 @@ LL | w.write(b"hello world").await.unwrap(); = help: use `AsyncWriteExt::write_all` instead, or handle partial writes error: read amount is not handled - --> $DIR/unused_io_amount.rs:133:5 + --> $DIR/unused_io_amount.rs:134:5 | LL | r.read(&mut buf[..]).await.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use `AsyncReadExt::read_exact` instead, or handle partial reads -error: aborting due to 20 previous errors +error: written amount is not handled + --> $DIR/unused_io_amount.rs:147:11 + | +LL | match s.write(b"test") { + | ^^^^^^^^^^^^^^^^ + | + = help: use `Write::write_all` instead, or handle partial writes +note: the result is consumed here, but the amount of I/O bytes remains unhandled + --> $DIR/unused_io_amount.rs:149:9 + | +LL | Ok(_) => todo!(), + | ^^^^^^^^^^^^^^^^ + +error: read amount is not handled + --> $DIR/unused_io_amount.rs:155:11 + | +LL | match s.read(&mut buf) { + | ^^^^^^^^^^^^^^^^ + | + = help: use `Read::read_exact` instead, or handle partial reads +note: the result is consumed here, but the amount of I/O bytes remains unhandled + --> $DIR/unused_io_amount.rs:157:9 + | +LL | Ok(_) => todo!(), + | ^^^^^^^^^^^^^^^^ + +error: read amount is not handled + --> $DIR/unused_io_amount.rs:164:11 + | +LL | match s.read(&mut [0u8; 4]) { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `Read::read_exact` instead, or handle partial reads +note: the result is consumed here, but the amount of I/O bytes remains unhandled + --> $DIR/unused_io_amount.rs:166:9 + | +LL | Ok(_) => todo!(), + | ^^^^^^^^^^^^^^^^ + +error: written amount is not handled + --> $DIR/unused_io_amount.rs:173:11 + | +LL | match s.write(b"test") { + | ^^^^^^^^^^^^^^^^ + | + = help: use `Write::write_all` instead, or handle partial writes +note: the result is consumed here, but the amount of I/O bytes remains unhandled + --> $DIR/unused_io_amount.rs:175:9 + | +LL | Ok(_) => todo!(), + | ^^^^^^^^^^^^^^^^ + +error: read amount is not handled + --> $DIR/unused_io_amount.rs:186:8 + | +LL | if let Ok(_) = s.read(&mut [0u8; 4]) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `Read::read_exact` instead, or handle partial reads +note: the result is consumed here, but the amount of I/O bytes remains unhandled + --> $DIR/unused_io_amount.rs:186:12 + | +LL | if let Ok(_) = s.read(&mut [0u8; 4]) { + | ^^^^^ + +error: written amount is not handled + --> $DIR/unused_io_amount.rs:193:8 + | +LL | if let Ok(_) = s.write(b"test") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `Write::write_all` instead, or handle partial writes +note: the result is consumed here, but the amount of I/O bytes remains unhandled + --> $DIR/unused_io_amount.rs:193:12 + | +LL | if let Ok(_) = s.write(b"test") { + | ^^^^^ + +error: written amount is not handled + --> $DIR/unused_io_amount.rs:200:8 + | +LL | if let Ok(..) = s.write(b"test") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `Write::write_all` instead, or handle partial writes +note: the result is consumed here, but the amount of I/O bytes remains unhandled + --> $DIR/unused_io_amount.rs:200:12 + | +LL | if let Ok(..) = s.write(b"test") { + | ^^^^^^ + +error: aborting due to 28 previous errors From 95a084f2eb24465cc9bed7f3998ae7f7076f833a Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 21 Jan 2024 03:21:54 +0100 Subject: [PATCH 158/676] [`multiple_crate_versions`]: add a configuration option for allowed duplicate dependencies --- CHANGELOG.md | 1 + book/src/lint_configuration.md | 10 ++++++++++ clippy_config/src/conf.rs | 4 ++++ clippy_lints/src/cargo/mod.rs | 6 +++++- clippy_lints/src/cargo/multiple_crate_versions.rs | 9 +++++++-- clippy_lints/src/lib.rs | 2 ++ .../12176_allow_duplicate_crates/Cargo.toml | 10 ++++++++++ .../12176_allow_duplicate_crates/clippy.toml | 1 + .../12176_allow_duplicate_crates/src/main.rs | 3 +++ tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr | 2 ++ 10 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml create mode 100644 tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/clippy.toml create mode 100644 tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/src/main.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index db4b4c2aef60c..5fa45ceeb39be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5815,6 +5815,7 @@ Released 2018-09-13 [`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments [`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles +[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates [`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items [`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 32c19d851feb2..7f7aff92bf19b 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -768,6 +768,16 @@ Additional dotfiles (files or directories starting with a dot) to allow * [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext) +## `allowed-duplicate-crates` +A list of crate names to allow duplicates of + +**Default Value:** `[]` + +--- +**Affected lints:** +* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions) + + ## `enforce-iter-loop-reborrow` Whether to recommend using implicit into iter for reborrowed values. diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 3ba7c5647968a..626b23f730999 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -523,6 +523,10 @@ define_Conf! { /// /// Additional dotfiles (files or directories starting with a dot) to allow (allowed_dotfiles: FxHashSet = FxHashSet::default()), + /// Lint: MULTIPLE_CRATE_VERSIONS. + /// + /// A list of crate names to allow duplicates of + (allowed_duplicate_crates: FxHashSet = FxHashSet::default()), /// Lint: EXPLICIT_ITER_LOOP. /// /// Whether to recommend using implicit into iter for reborrowed values. diff --git a/clippy_lints/src/cargo/mod.rs b/clippy_lints/src/cargo/mod.rs index fea6924d89e91..d8107f61f371c 100644 --- a/clippy_lints/src/cargo/mod.rs +++ b/clippy_lints/src/cargo/mod.rs @@ -6,6 +6,7 @@ mod wildcard_dependencies; use cargo_metadata::MetadataCommand; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_lint_allowed; +use rustc_data_structures::fx::FxHashSet; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_session::impl_lint_pass; @@ -128,6 +129,8 @@ declare_clippy_lint! { /// ### Known problems /// Because this can be caused purely by the dependencies /// themselves, it's not always possible to fix this issue. + /// In those cases, you can allow that specific crate using + /// the `allowed_duplicate_crates` configuration option. /// /// ### Example /// ```toml @@ -163,6 +166,7 @@ declare_clippy_lint! { } pub struct Cargo { + pub allowed_duplicate_crates: FxHashSet, pub ignore_publish: bool, } @@ -208,7 +212,7 @@ impl LateLintPass<'_> for Cargo { { match MetadataCommand::new().exec() { Ok(metadata) => { - multiple_crate_versions::check(cx, &metadata); + multiple_crate_versions::check(cx, &metadata, &self.allowed_duplicate_crates); }, Err(e) => { for lint in WITH_DEPS_LINTS { diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs index 57b7b7497fe24..3f30a77fcfe47 100644 --- a/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -3,13 +3,14 @@ use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId}; use clippy_utils::diagnostics::span_lint; use itertools::Itertools; +use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::LOCAL_CRATE; use rustc_lint::LateContext; use rustc_span::DUMMY_SP; use super::MULTIPLE_CRATE_VERSIONS; -pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { +pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, allowed_duplicate_crates: &FxHashSet) { let local_name = cx.tcx.crate_name(LOCAL_CRATE); let mut packages = metadata.packages.clone(); packages.sort_by(|a, b| a.name.cmp(&b.name)); @@ -31,7 +32,11 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { } }) { - for (name, group) in &packages.iter().group_by(|p| p.name.clone()) { + for (name, group) in &packages + .iter() + .filter(|p| !allowed_duplicate_crates.contains(&p.name)) + .group_by(|p| &p.name) + { let group: Vec<&Package> = group.collect(); if group.len() <= 1 { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8004590e8e75d..feb4d188f3978 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -574,6 +574,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { warn_on_all_wildcard_imports, check_private_items, pub_underscore_fields_behavior, + ref allowed_duplicate_crates, blacklisted_names: _, cyclomatic_complexity_threshold: _, @@ -947,6 +948,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| { Box::new(cargo::Cargo { ignore_publish: cargo_ignore_publish, + allowed_duplicate_crates: allowed_duplicate_crates.clone(), }) }); store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef)); diff --git a/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml new file mode 100644 index 0000000000000..79317659ac072 --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "multiple_crate_versions" +version = "0.1.0" +publish = false + +[workspace] + +[dependencies] +winapi = "0.2" +ansi_term = "=0.11.0" diff --git a/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/clippy.toml b/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/clippy.toml new file mode 100644 index 0000000000000..121361de2fe0b --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/clippy.toml @@ -0,0 +1 @@ +allowed-duplicate-crates = ["winapi"] diff --git a/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/src/main.rs b/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/src/main.rs new file mode 100644 index 0000000000000..4bc61dd62992f --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/src/main.rs @@ -0,0 +1,3 @@ +#![warn(clippy::multiple_crate_versions)] + +fn main() {} diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index ed4fb84df1ae1..09fc9dfa463eb 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -11,6 +11,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-private-module-inception allow-unwrap-in-tests allowed-dotfiles + allowed-duplicate-crates allowed-idents-below-min-chars allowed-scripts arithmetic-side-effects-allowed @@ -87,6 +88,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-private-module-inception allow-unwrap-in-tests allowed-dotfiles + allowed-duplicate-crates allowed-idents-below-min-chars allowed-scripts arithmetic-side-effects-allowed From 1a9ef233b736e063d8b51437022b366c77d5ac75 Mon Sep 17 00:00:00 2001 From: r0cky Date: Sun, 21 Jan 2024 12:56:23 +0800 Subject: [PATCH 159/676] 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 384b2ab37529ba0ad07ea8271baf0f212bab2e5a Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sun, 21 Jan 2024 05:39:01 +0000 Subject: [PATCH 160/676] 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 ad3a534b7ed0a..aa05d224c21fe 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3deb9bbf84f6431ebcbb7cbdbe3d89bc2636bc1b +867d39cdf625e4db4b381faff993346582e598b4 From 60ef392a2a0eedfc1093e5daf7c04030dc116b5d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 21 Jan 2024 11:16:00 +0000 Subject: [PATCH 161/676] Rustup to rustc 1.77.0-nightly (4cb17b4e7 2024-01-20) --- patches/0001-rand-Allow-warnings.patch | 24 ++++++++++++++++++++++++ patches/stdlib-lock.toml | 4 ++-- rust-toolchain | 2 +- src/driver/jit.rs | 7 +++---- 4 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 patches/0001-rand-Allow-warnings.patch diff --git a/patches/0001-rand-Allow-warnings.patch b/patches/0001-rand-Allow-warnings.patch new file mode 100644 index 0000000000000..ae46e957efa04 --- /dev/null +++ b/patches/0001-rand-Allow-warnings.patch @@ -0,0 +1,24 @@ +From 8330c138c91f71ad43b38c026ee14b154f34a1b8 Mon Sep 17 00:00:00 2001 +From: bjorn3 <17426603+bjorn3@users.noreply.github.com> +Date: Sun, 21 Jan 2024 11:12:19 +0000 +Subject: [PATCH] Allow warnings + +--- + rand_core/src/lib.rs | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs +index a5a7fb1..6c84068 100644 +--- a/rand_core/src/lib.rs ++++ b/rand_core/src/lib.rs +@@ -34,7 +34,6 @@ + )] + #![deny(missing_docs)] + #![deny(missing_debug_implementations)] +-#![doc(test(attr(allow(unused_variables), deny(warnings))))] + #![cfg_attr(doc_cfg, feature(doc_cfg))] + #![no_std] + +-- +2.34.1 + diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml index 8e213f71c3f38..ad63b0768d313 100644 --- a/patches/stdlib-lock.toml +++ b/patches/stdlib-lock.toml @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.104" +version = "0.1.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3f9035afc33f4358773239573f7d121099856753e1bbd2a6a5207098fc741" +checksum = "f4ab134a739bafec76aa91ccb15d519a54e569350644a1fea6528d5a0d407e22" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/rust-toolchain b/rust-toolchain index a086c0293601f..5fdaa2a931082 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-12-31" +channel = "nightly-2024-01-21" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 50d9f287e74c9..6b2b946db02b6 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -321,10 +321,9 @@ fn dep_symbol_lookup_fn( Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { let name = crate_info.crate_name[&cnum]; - sess.dcx() - .struct_err(format!("Can't load static lib {}", name)) - .note("rustc_codegen_cranelift can only load dylibs in JIT mode.") - .emit(); + let mut diag = sess.dcx().struct_err(format!("Can't load static lib {}", name)); + diag.note("rustc_codegen_cranelift can only load dylibs in JIT mode."); + diag.emit(); } Linkage::Dynamic => { dylib_paths.push(src.dylib.as_ref().unwrap().0.clone()); From 24361a1b99b122806afdc01c3aae1c43fdcc7e0a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 21 Jan 2024 11:38:13 +0000 Subject: [PATCH 162/676] Fix portable-simd tests --- src/intrinsics/llvm_aarch64.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index f6f3b85d3ef81..e66bcbf4e40e5 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -243,6 +243,20 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( } // FIXME generalize vector types + "llvm.aarch64.neon.tbl1.v8i8" => { + intrinsic_args!(fx, args => (t, idx); intrinsic); + + let zero = fx.bcx.ins().iconst(types::I8, 0); + for i in 0..8 { + let idx_lane = idx.value_lane(fx, i).load_scalar(fx); + let is_zero = + fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThanOrEqual, idx_lane, 16); + let t_idx = fx.bcx.ins().uextend(fx.pointer_type, idx_lane); + let t_lane = t.value_lane_dyn(fx, t_idx).load_scalar(fx); + let res = fx.bcx.ins().select(is_zero, zero, t_lane); + ret.place_lane(fx, i).to_ptr().store(fx, res, MemFlags::trusted()); + } + } "llvm.aarch64.neon.tbl1.v16i8" => { intrinsic_args!(fx, args => (t, idx); intrinsic); From 7092c660077d185df375eaf07d649be2b49018d0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 21 Jan 2024 13:11:00 +0000 Subject: [PATCH 163/676] update lockfile --- src/tools/miri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 6cd22a9151897..8cd996d85645b 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -486,9 +486,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "measureme" -version = "10.1.2" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe" +checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d" dependencies = [ "log", "memmap2", From ad4d90b4a95887834ac93339ff388ed58cc8840d Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 21 Jan 2024 14:54:01 +0100 Subject: [PATCH 164/676] respect `#[allow]` attribute in `single_call_fn` lint --- clippy_lints/src/single_call_fn.rs | 12 +++++++----- tests/ui/single_call_fn.rs | 11 +++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs index 8e181c3ccc743..0387742077447 100644 --- a/clippy_lints/src/single_call_fn.rs +++ b/clippy_lints/src/single_call_fn.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::{is_from_proc_macro, is_in_test_function}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; @@ -88,16 +88,18 @@ impl<'tcx> LateLintPass<'tcx> for SingleCallFn { }; cx.tcx.hir().visit_all_item_likes_in_crate(&mut v); - for usage in self.def_id_to_usage.values() { + for (&def_id, usage) in &self.def_id_to_usage { let single_call_fn_span = usage.0; if let [caller_span] = *usage.1 { - span_lint_and_help( + span_lint_hir_and_then( cx, SINGLE_CALL_FN, + cx.tcx.local_def_id_to_hir_id(def_id), single_call_fn_span, "this function is only used once", - Some(caller_span), - "used here", + |diag| { + diag.span_help(caller_span, "used here"); + }, ); } } diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs index 3cc8061647dff..c20214fecccea 100644 --- a/tests/ui/single_call_fn.rs +++ b/tests/ui/single_call_fn.rs @@ -69,6 +69,17 @@ fn e() { #[test] fn k() {} +mod issue12182 { + #[allow(clippy::single_call_fn)] + fn print_foo(text: &str) { + println!("{text}"); + } + + fn use_print_foo() { + print_foo("foo"); + } +} + #[test] fn l() { k(); 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 165/676] 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(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit`) note: required because it appears within the type `I` diff --git a/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr b/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr index 6752a484448c5..2d7956f1958c5 100644 --- a/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr +++ b/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `[u8; 1]: Test` is not satisfied --> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:11:22 | LL | let x: [u8; 1] = needs_test(); - | ^^^^^^^^^^ the trait `Test` is not implemented for `[u8; 1]` + | ^^^^^^^^^^^^ the trait `Test` is not implemented for `[u8; 1]` | = help: the trait `Test` is implemented for `&[u8]` note: required by a bound in `needs_test` diff --git a/tests/ui/error-codes/E0283.stderr b/tests/ui/error-codes/E0283.stderr index 6008809f050f8..fc08395a2b0df 100644 --- a/tests/ui/error-codes/E0283.stderr +++ b/tests/ui/error-codes/E0283.stderr @@ -5,7 +5,7 @@ LL | fn create() -> u32; | ------------------- `Coroutine::create` defined here ... LL | let cont: u32 = Coroutine::create(); - | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | diff --git a/tests/ui/error-codes/E0790.stderr b/tests/ui/error-codes/E0790.stderr index f559abae39780..6338a10b6af9d 100644 --- a/tests/ui/error-codes/E0790.stderr +++ b/tests/ui/error-codes/E0790.stderr @@ -5,7 +5,7 @@ LL | fn my_fn(); | ----------- `MyTrait::my_fn` defined here ... LL | MyTrait::my_fn(); - | ^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | @@ -33,7 +33,7 @@ LL | fn my_fn(); | ----------- `MyTrait::my_fn` defined here ... LL | inner::MyTrait::my_fn(); - | ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | @@ -61,7 +61,7 @@ LL | fn my_fn(); | ----------- `MyTrait2::my_fn` defined here ... LL | MyTrait2::my_fn(); - | ^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr index 77aa37cefe363..b322ea41c436d 100644 --- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr +++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr @@ -2,7 +2,7 @@ error[E0277]: expected a `Fn(&'w ())` closure, found `fn(&'w ())` --> $DIR/fn-ptr.rs:12:5 | LL | ice(); - | ^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())` + | ^^^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())` | = help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())` note: required by a bound in `ice` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr index 3240518fbbe08..e60531a876be1 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr @@ -13,7 +13,7 @@ error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied --> $DIR/issue-85455.rs:8:5 | LL | callee:: >::Associated>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr index a2ec96f1a2d0f..f42fc59536c43 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr @@ -2,13 +2,13 @@ error[E0277]: the trait bound `for<'a> <_ as Trait<'a>>::Out: Copy` is not satis --> $DIR/norm-before-method-resolution.rs:22:17 | LL | let _: () = weird_bound(); - | ^^^^^^^^^^^ the trait `for<'a> Copy` is not implemented for `<_ as Trait<'a>>::Out` + | ^^^^^^^^^^^^^ the trait `for<'a> Copy` is not implemented for `<_ as Trait<'a>>::Out` | note: this is a known limitation of the trait solver that will be lifted in the future --> $DIR/norm-before-method-resolution.rs:22:17 | LL | let _: () = weird_bound(); - | ^^^^^^^^^^^ try adding turbofish arguments to this expression to specify the types manually, even if it's redundant + | ^^^^^^^^^^^^^ try adding turbofish arguments to this expression to specify the types manually, even if it's redundant note: required by a bound in `weird_bound` --> $DIR/norm-before-method-resolution.rs:18:40 | diff --git a/tests/ui/impl-trait/cross-return-site-inference.stderr b/tests/ui/impl-trait/cross-return-site-inference.stderr index 8ee3e9abf9ccb..5512c234af985 100644 --- a/tests/ui/impl-trait/cross-return-site-inference.stderr +++ b/tests/ui/impl-trait/cross-return-site-inference.stderr @@ -13,7 +13,7 @@ error[E0790]: cannot call associated function on trait without specifying the co --> $DIR/cross-return-site-inference.rs:38:16 | LL | return Err(From::from("foo")); - | ^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | @@ -24,7 +24,7 @@ error[E0790]: cannot call associated function on trait without specifying the co --> $DIR/cross-return-site-inference.rs:44:9 | LL | Err(From::from("foo")) - | ^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs index 650cb3870d581..daf29a0005dec 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs @@ -20,7 +20,6 @@ impl dyn MyTrait { MyTrait::foo(&self) //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied - //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied //~| ERROR the trait `MyTrait` cannot be made into an object } } diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr index 01de3e531952c..90285d512ef03 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr @@ -32,14 +32,6 @@ LL | MyTrait::foo(&self) | = help: the trait `MyTrait` is implemented for `Outer` -error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 - | -LL | MyTrait::foo(&self) - | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` - | - = help: the trait `MyTrait` is implemented for `Outer` - error[E0038]: the trait `MyTrait` cannot be made into an object --> $DIR/cycle-effective-visibilities-during-object-safety.rs:16:6 | @@ -72,7 +64,7 @@ LL | fn foo(&self) -> impl Marker; = help: consider moving `foo` to another trait = help: only type `Outer` implements the trait, consider using it directly instead -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0038, E0277. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/in-trait/issue-102140.rs b/tests/ui/impl-trait/in-trait/issue-102140.rs index 7960018482fce..9d703cf0df1bc 100644 --- a/tests/ui/impl-trait/in-trait/issue-102140.rs +++ b/tests/ui/impl-trait/in-trait/issue-102140.rs @@ -20,7 +20,6 @@ impl dyn MyTrait { MyTrait::foo(&self) //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied - //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied } } diff --git a/tests/ui/impl-trait/in-trait/issue-102140.stderr b/tests/ui/impl-trait/in-trait/issue-102140.stderr index 9cd2cdfd1a53e..dc3dcc114aed5 100644 --- a/tests/ui/impl-trait/in-trait/issue-102140.stderr +++ b/tests/ui/impl-trait/in-trait/issue-102140.stderr @@ -20,14 +20,6 @@ LL | MyTrait::foo(&self) | = help: the trait `MyTrait` is implemented for `Outer` -error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/issue-102140.rs:20:9 - | -LL | MyTrait::foo(&self) - | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` - | - = help: the trait `MyTrait` is implemented for `Outer` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr index 9be1828648011..546e679f2d0bc 100644 --- a/tests/ui/inference/erase-type-params-in-label.stderr +++ b/tests/ui/inference/erase-type-params-in-label.stderr @@ -2,7 +2,7 @@ error[E0283]: type annotations needed for `Foo` --> $DIR/erase-type-params-in-label.rs:2:9 | LL | let foo = foo(1, ""); - | ^^^ --- type must be known at this point + | ^^^ ---------- type must be known at this point | = note: cannot satisfy `_: Default` note: required by a bound in `foo` @@ -19,7 +19,7 @@ error[E0283]: type annotations needed for `Bar` --> $DIR/erase-type-params-in-label.rs:5:9 | LL | let bar = bar(1, ""); - | ^^^ --- type must be known at this point + | ^^^ ---------- type must be known at this point | = note: cannot satisfy `_: Default` note: required by a bound in `bar` diff --git a/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr b/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr index aeebf68e67576..5576e17546873 100644 --- a/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr +++ b/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr @@ -2,7 +2,7 @@ error[E0790]: cannot call associated function on trait without specifying the co --> $DIR/infer-var-for-self-param.rs:5:14 | LL | let _ = (Default::default(),); - | ^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | diff --git a/tests/ui/inference/need_type_info/type-alias.stderr b/tests/ui/inference/need_type_info/type-alias.stderr index a33f49baf549f..cc7053bf385ff 100644 --- a/tests/ui/inference/need_type_info/type-alias.stderr +++ b/tests/ui/inference/need_type_info/type-alias.stderr @@ -2,13 +2,13 @@ error[E0282]: type annotations needed --> $DIR/type-alias.rs:12:5 | LL | DirectAlias::new() - | ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` error[E0282]: type annotations needed --> $DIR/type-alias.rs:32:5 | LL | DirectButWithDefaultAlias::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-56199.stderr b/tests/ui/issues/issue-56199.stderr index 7aaf8e4ac2f14..eb6d7005979f6 100644 --- a/tests/ui/issues/issue-56199.stderr +++ b/tests/ui/issues/issue-56199.stderr @@ -10,7 +10,7 @@ error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:8:17 | LL | let _ = Self(); - | ^^^^ + | ^^^^^^ | = help: did you mean to use one of the enum's variants? @@ -24,7 +24,7 @@ error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:17:17 | LL | let _ = Self(); - | ^^^^ help: use curly brackets: `Self { /* fields */ }` + | ^^^^^^ help: use curly brackets: `Self { /* fields */ }` error: aborting due to 4 previous errors diff --git a/tests/ui/iterators/issue-28098.rs b/tests/ui/iterators/issue-28098.rs index 80c77edae9eb1..62a90d90d12de 100644 --- a/tests/ui/iterators/issue-28098.rs +++ b/tests/ui/iterators/issue-28098.rs @@ -2,14 +2,12 @@ fn main() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator //~| ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator for _ in false {} //~^ ERROR `bool` is not an iterator let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator other() } @@ -20,11 +18,9 @@ pub fn other() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator //~| ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator for _ in false {} //~^ ERROR `bool` is not an iterator diff --git a/tests/ui/iterators/issue-28098.stderr b/tests/ui/iterators/issue-28098.stderr index 3256e57d4361b..a724f03ad4af1 100644 --- a/tests/ui/iterators/issue-28098.stderr +++ b/tests/ui/iterators/issue-28098.stderr @@ -8,16 +8,8 @@ LL | let _ = Iterator::next(&mut ()); | = help: the trait `Iterator` is not implemented for `()` -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:2:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:7:14 + --> $DIR/issue-28098.rs:6:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator @@ -26,7 +18,7 @@ LL | for _ in false {} = note: required for `bool` to implement `IntoIterator` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:10:28 + --> $DIR/issue-28098.rs:9:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -35,24 +27,16 @@ LL | let _ = Iterator::next(&mut ()); | = help: the trait `Iterator` is not implemented for `()` -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:10:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:2:13 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:20:28 + --> $DIR/issue-28098.rs:18:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -62,15 +46,7 @@ LL | let _ = Iterator::next(&mut ()); = help: the trait `Iterator` is not implemented for `()` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:20:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:25:28 + --> $DIR/issue-28098.rs:22:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -79,16 +55,8 @@ LL | let _ = Iterator::next(&mut ()); | = help: the trait `Iterator` is not implemented for `()` -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:25:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:29:14 + --> $DIR/issue-28098.rs:25:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator @@ -97,13 +65,13 @@ LL | for _ in false {} = note: required for `bool` to implement `IntoIterator` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:20:13 + --> $DIR/issue-28098.rs:18:13 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` -error: aborting due to 12 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/mismatched_types/E0631.stderr b/tests/ui/mismatched_types/E0631.stderr index 9ba8f5035c5f6..dcd66c28e3cfb 100644 --- a/tests/ui/mismatched_types/E0631.stderr +++ b/tests/ui/mismatched_types/E0631.stderr @@ -2,8 +2,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/E0631.rs:7:5 | LL | foo(|_: isize| {}); - | ^^^ ---------- found signature defined here - | | + | ^^^^----------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `fn(usize) -> _` @@ -18,8 +19,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/E0631.rs:8:5 | LL | bar(|_: isize| {}); - | ^^^ ---------- found signature defined here - | | + | ^^^^----------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `fn(usize) -> _` diff --git a/tests/ui/mismatched_types/closure-arg-count.stderr b/tests/ui/mismatched_types/closure-arg-count.stderr index 2ecab9f024a12..0e2ca8feec545 100644 --- a/tests/ui/mismatched_types/closure-arg-count.stderr +++ b/tests/ui/mismatched_types/closure-arg-count.stderr @@ -49,8 +49,9 @@ error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:13:5 | LL | f(|| panic!()); - | ^ -- takes 0 arguments - | | + | ^^--^^^^^^^^^^ + | | | + | | takes 0 arguments | expected closure that takes 1 argument | note: required by a bound in `f` @@ -67,8 +68,9 @@ error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:15:5 | LL | f( move || panic!()); - | ^ ---------- takes 0 arguments - | | + | ^^^^----------^^^^^^^^^^ + | | | + | | takes 0 arguments | expected closure that takes 1 argument | note: required by a bound in `f` diff --git a/tests/ui/on-unimplemented/multiple-impls.rs b/tests/ui/on-unimplemented/multiple-impls.rs index a32fd4566231d..b74957ebcd406 100644 --- a/tests/ui/on-unimplemented/multiple-impls.rs +++ b/tests/ui/on-unimplemented/multiple-impls.rs @@ -33,13 +33,10 @@ fn main() { Index::index(&[] as &[i32], 2u32); //~^ ERROR E0277 //~| ERROR E0277 - //~| ERROR E0277 Index::index(&[] as &[i32], Foo(2u32)); //~^ ERROR E0277 //~| ERROR E0277 - //~| ERROR E0277 Index::index(&[] as &[i32], Bar(2u32)); //~^ ERROR E0277 //~| ERROR E0277 - //~| ERROR E0277 } diff --git a/tests/ui/on-unimplemented/multiple-impls.stderr b/tests/ui/on-unimplemented/multiple-impls.stderr index 3d0e36db75215..f59c93a7c375e 100644 --- a/tests/ui/on-unimplemented/multiple-impls.stderr +++ b/tests/ui/on-unimplemented/multiple-impls.stderr @@ -11,19 +11,8 @@ LL | Index::index(&[] as &[i32], 2u32); <[i32] as Index>> <[i32] as Index>> -error[E0277]: the trait bound `[i32]: Index` is not satisfied - --> $DIR/multiple-impls.rs:33:5 - | -LL | Index::index(&[] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message - | - = help: the trait `Index` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:37:33 + --> $DIR/multiple-impls.rs:36:33 | LL | Index::index(&[] as &[i32], Foo(2u32)); | ------------ ^^^^^^^^^ on impl for Foo @@ -35,19 +24,8 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); <[i32] as Index>> <[i32] as Index>> -error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:37:5 - | -LL | Index::index(&[] as &[i32], Foo(2u32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo - | - = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:41:33 + --> $DIR/multiple-impls.rs:39:33 | LL | Index::index(&[] as &[i32], Bar(2u32)); | ------------ ^^^^^^^^^ on impl for Bar @@ -59,22 +37,11 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); <[i32] as Index>> <[i32] as Index>> -error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:41:5 - | -LL | Index::index(&[] as &[i32], Bar(2u32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar - | - = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:5 | LL | Index::index(&[] as &[i32], 2u32); - | ^^^^^^^^^^^^ trait message + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` = help: the following other types implement trait `Index`: @@ -82,10 +49,10 @@ LL | Index::index(&[] as &[i32], 2u32); <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:37:5 + --> $DIR/multiple-impls.rs:36:5 | LL | Index::index(&[] as &[i32], Foo(2u32)); - | ^^^^^^^^^^^^ on impl for Foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index>` is not implemented for `[i32]` = help: the following other types implement trait `Index`: @@ -93,16 +60,16 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:41:5 + --> $DIR/multiple-impls.rs:39:5 | LL | Index::index(&[] as &[i32], Bar(2u32)); - | ^^^^^^^^^^^^ on impl for Bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index>` is not implemented for `[i32]` = help: the following other types implement trait `Index`: <[i32] as Index>> <[i32] as Index>> -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/on-impl.rs b/tests/ui/on-unimplemented/on-impl.rs index d0537810ce11e..ab3e67d01fe44 100644 --- a/tests/ui/on-unimplemented/on-impl.rs +++ b/tests/ui/on-unimplemented/on-impl.rs @@ -22,5 +22,4 @@ fn main() { Index::::index(&[1, 2, 3] as &[i32], 2u32); //~^ ERROR E0277 //~| ERROR E0277 - //~| ERROR E0277 } diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr index 3a0b8353fa5eb..c7d2a78af6cba 100644 --- a/tests/ui/on-unimplemented/on-impl.stderr +++ b/tests/ui/on-unimplemented/on-impl.stderr @@ -20,16 +20,6 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); = help: the trait `Index` is implemented for `[i32]` = help: for that trait implementation, expected `usize`, found `u32` -error[E0277]: the trait bound `[i32]: Index` is not satisfied - --> $DIR/on-impl.rs:22:5 - | -LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice - | - = help: the trait `Index` is not implemented for `[i32]` - = help: the trait `Index` is implemented for `[i32]` - = help: for that trait implementation, expected `usize`, found `u32` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/on-trait.stderr b/tests/ui/on-unimplemented/on-trait.stderr index 4847a1a5a6119..4097ee1350dbc 100644 --- a/tests/ui/on-unimplemented/on-trait.stderr +++ b/tests/ui/on-unimplemented/on-trait.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Option>: MyFromIterator<&u8>` is not sati --> $DIR/on-trait.rs:28:30 | LL | let y: Option> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() - | ^^^^^^^ a collection of type `Option>` cannot be built from an iterator over elements of type `&u8` + | ^^^^^^^^^^^^^^^^^ a collection of type `Option>` cannot be built from an iterator over elements of type `&u8` | = help: the trait `MyFromIterator<&u8>` is not implemented for `Option>` help: this trait has no implementations, consider adding one @@ -20,7 +20,7 @@ error[E0277]: the trait bound `String: Foo` is not satisfied --> $DIR/on-trait.rs:31:21 | LL | let x: String = foobar(); - | ^^^^^^ test error `String` with `u8` `_` `u32` in `Foo` + | ^^^^^^^^ test error `String` with `u8` `_` `u32` in `Foo` | = help: the trait `Foo` is not implemented for `String` help: this trait has no implementations, consider adding one diff --git a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr index 3681a796c53ed..17138a6f07921 100644 --- a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr +++ b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr @@ -30,8 +30,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/recover-fn-trait-from-fn-kw.rs:10:5 | LL | foo2(|_: ()| {}); - | ^^^^ ------- found signature defined here - | | + | ^^^^^-------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `fn(i32) -> _` diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index e6835bb54fb3d..d41f5808752c9 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t --> $DIR/str-mut-idx.rs:4:15 | LL | s[1..2] = bot(); - | ^^^ doesn't have a size known at compile-time + | ^^^^^ 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` diff --git a/tests/ui/suggestions/issue-104327.stderr b/tests/ui/suggestions/issue-104327.stderr index 325b6b6eb4b63..1bad82d471e04 100644 --- a/tests/ui/suggestions/issue-104327.stderr +++ b/tests/ui/suggestions/issue-104327.stderr @@ -5,7 +5,7 @@ LL | fn f() {} | --------- `Foo::f` defined here ... LL | Foo::f(); - | ^^^^^^ cannot call associated function of trait + | ^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/suggestions/issue-104328.stderr b/tests/ui/suggestions/issue-104328.stderr index a592621834127..3c5e6f16289e0 100644 --- a/tests/ui/suggestions/issue-104328.stderr +++ b/tests/ui/suggestions/issue-104328.stderr @@ -5,7 +5,7 @@ LL | fn f() {} | --------- `Foo::f` defined here ... LL | Foo::f(); - | ^^^^^^ cannot call associated function of trait + | ^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/suggestions/issue-89333.stderr b/tests/ui/suggestions/issue-89333.stderr index 761de7f252184..9df850ec9de08 100644 --- a/tests/ui/suggestions/issue-89333.stderr +++ b/tests/ui/suggestions/issue-89333.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> &'a _: Trait` is not satisfied --> $DIR/issue-89333.rs:6:5 | LL | test(&|| 0); - | ^^^^ the trait `for<'a> Trait` is not implemented for `&'a _` + | ^^^^^^^^^^^ the trait `for<'a> Trait` is not implemented for `&'a _` | help: this trait has no implementations, consider adding one --> $DIR/issue-89333.rs:9:1 diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr index 125a8b44f2f0a..485015a98f2a7 100644 --- a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&mut usize: Default` is not satisfied --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9 | LL | foo(Default::default()); - | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize` + | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize` | help: consider mutably borrowing here | @@ -13,7 +13,7 @@ error[E0277]: the trait bound `&usize: Default` is not satisfied --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9 | LL | bar(Default::default()); - | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize` + | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize` | help: consider borrowing here | diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr index fb9900bc57bbc..857495f4a156d 100644 --- a/tests/ui/traits/bad-sized.stderr +++ b/tests/ui/traits/bad-sized.stderr @@ -23,7 +23,7 @@ error[E0277]: the size for values of type `dyn Trait` cannot be known at compila --> $DIR/bad-sized.rs:4:37 | LL | let x: Vec = Vec::new(); - | ^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^ 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::::new` diff --git a/tests/ui/traits/inductive-overflow/lifetime.stderr b/tests/ui/traits/inductive-overflow/lifetime.stderr index b34bb0361f1e4..406f4d25dce3f 100644 --- a/tests/ui/traits/inductive-overflow/lifetime.stderr +++ b/tests/ui/traits/inductive-overflow/lifetime.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow evaluating the requirement `Box>>: NotAuto` --> $DIR/lifetime.rs:29:5 | LL | is_send::>>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required for `X>` to implement `NotAuto` --> $DIR/lifetime.rs:19:12 diff --git a/tests/ui/traits/inductive-overflow/simultaneous.stderr b/tests/ui/traits/inductive-overflow/simultaneous.stderr index b9a746e44ba01..29456d88b1bfc 100644 --- a/tests/ui/traits/inductive-overflow/simultaneous.stderr +++ b/tests/ui/traits/inductive-overflow/simultaneous.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum` --> $DIR/simultaneous.rs:18:5 | LL | is_ee(4); - | ^^^^^ + | ^^^^^^^^ | note: required for `{integer}` to implement `Combo` --> $DIR/simultaneous.rs:11:34 diff --git a/tests/ui/traits/inductive-overflow/supertrait.stderr b/tests/ui/traits/inductive-overflow/supertrait.stderr index f2dccbbbb2cb6..99e9c8f93b8a4 100644 --- a/tests/ui/traits/inductive-overflow/supertrait.stderr +++ b/tests/ui/traits/inductive-overflow/supertrait.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow evaluating the requirement `NoClone: Magic` --> $DIR/supertrait.rs:13:18 | LL | let (a, b) = copy(NoClone); - | ^^^^ + | ^^^^^^^^^^^^^ | note: required for `NoClone` to implement `Magic` --> $DIR/supertrait.rs:5:16 diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr index 0d0bf88616c86..6092c194a8757 100644 --- a/tests/ui/traits/inductive-overflow/two-traits.stderr +++ b/tests/ui/traits/inductive-overflow/two-traits.stderr @@ -18,7 +18,7 @@ error[E0275]: overflow evaluating the requirement `*mut (): Magic` --> $DIR/two-traits.rs:20:5 | LL | wizard::<*mut ()>(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `wizard` --> $DIR/two-traits.rs:17:14 diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index 8fddbd7ecdcc8..01b90977d7181 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -22,8 +22,7 @@ impl Foo for () { fn main() { let x = String::from("hello, world"); drop(<() as Foo>::copy_me(&x)); - //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized` - //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` + //~^ ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index 874644317ebd3..1983360b658df 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -27,15 +27,6 @@ LL | drop(<() as Foo>::copy_me(&x)); | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Sized` - --> $DIR/alias-bound-unsound.rs:24:10 - | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) - = note: the return type of a function must have a statically known size - error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed` --> $DIR/alias-bound-unsound.rs:24:31 | @@ -61,6 +52,6 @@ LL | drop(<() as Foo>::copy_me(&x)); = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index e3be2931e1232..1b776d7198ea4 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `dyn Trait: Trait` is not satisfied --> $DIR/more-object-bound.rs:12:5 | LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait` | note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr index ee38c256e5f64..eedca879b0c8a 100644 --- a/tests/ui/traits/next-solver/object-unsafety.stderr +++ b/tests/ui/traits/next-solver/object-unsafety.stderr @@ -46,10 +46,7 @@ error[E0277]: the size for values of type ` as Setup>::From` --> $DIR/object-unsafety.rs:12:5 | LL | copy::>(t) - | ^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | doesn't have a size known at compile-time - | this returned value is of type ` as Setup>::From` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for ` as Setup>::From` = note: the return type of a function must have a statically known size diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.stderr b/tests/ui/traits/next-solver/specialization-unconstrained.stderr index ed4dafa1484c2..68232aacc0c5f 100644 --- a/tests/ui/traits/next-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/next-solver/specialization-unconstrained.stderr @@ -12,7 +12,7 @@ error[E0284]: type annotations needed: cannot satisfy `::Id == ( --> $DIR/specialization-unconstrained.rs:20:5 | LL | test::(); - | ^^^^^^^^^^^^^^^ cannot satisfy `::Id == ()` + | ^^^^^^^^^^^^^^^^^ cannot satisfy `::Id == ()` | note: required by a bound in `test` --> $DIR/specialization-unconstrained.rs:17:20 diff --git a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr index d5f2bfef19260..4694e7da500f3 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/bad-copy-cond.rs:7:5 | LL | foo(); - | ^^^ the trait `Copy` is not implemented for `T` + | ^^^^^ the trait `Copy` is not implemented for `T` | note: required by a bound in `foo` --> $DIR/bad-copy-cond.rs:4:26 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 d8db07277c500..f4deb169516cf 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr @@ -11,7 +11,7 @@ error[E0277]: the size for values of type `V` cannot be known at compilation tim --> $DIR/bad-sized-cond.rs:17:5 | LL | foo(); - | ^^^ doesn't have a size known at compile-time + | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `V` note: required by a bound in `foo` @@ -27,7 +27,7 @@ error[E0277]: `V` is not an iterator --> $DIR/bad-sized-cond.rs:20:5 | LL | bar(); - | ^^^ `V` is not an iterator + | ^^^^^ `V` is not an iterator | = help: the trait `Iterator` is not implemented for `V` = note: required for `V` to implement `IntoIterator` @@ -44,7 +44,7 @@ error[E0277]: the size for values of type `V` cannot be known at compilation tim --> $DIR/bad-sized-cond.rs:20:5 | LL | bar(); - | ^^^ doesn't have a size known at compile-time + | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `V` = note: required for `V` to implement `IntoIterator` diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr index 240bcef7df504..9a324c952931e 100644 --- a/tests/ui/traits/non_lifetime_binders/fail.stderr +++ b/tests/ui/traits/non_lifetime_binders/fail.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/fail.rs:19:5 | LL | fail(); - | ^^^^ the trait `Trait` is not implemented for `T` + | ^^^^^^ the trait `Trait` is not implemented for `T` | help: this trait has no implementations, consider adding one --> $DIR/fail.rs:6:1 @@ -31,7 +31,7 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/fail.rs:21:5 | LL | auto_trait(); - | ^^^^^^^^^^ `T` cannot be sent between threads safely + | ^^^^^^^^^^^^ `T` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `T` note: required by a bound in `auto_trait` diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr index 8cf32c89416a7..abbdecf2fe1db 100644 --- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr @@ -11,7 +11,7 @@ error[E0277]: can't compare `T` with `T` --> $DIR/foreach-partial-eq.rs:10:5 | LL | auto_trait(); - | ^^^^^^^^^^ no implementation for `T < T` and `T > T` + | ^^^^^^^^^^^^ no implementation for `T < T` and `T > T` | = help: the trait `PartialOrd` is not implemented for `T` note: required by a bound in `auto_trait` diff --git a/tests/ui/traits/static-method-generic-inference.stderr b/tests/ui/traits/static-method-generic-inference.stderr index 44c7c099832b5..80bdbbf350dfd 100644 --- a/tests/ui/traits/static-method-generic-inference.stderr +++ b/tests/ui/traits/static-method-generic-inference.stderr @@ -5,7 +5,7 @@ LL | fn new() -> T; | -------------- `HasNew::new` defined here ... LL | let _f: base::Foo = base::HasNew::new(); - | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/transmutability/region-infer.stderr b/tests/ui/transmutability/region-infer.stderr index 50d060cd47431..805862d6c4afc 100644 --- a/tests/ui/transmutability/region-infer.stderr +++ b/tests/ui/transmutability/region-infer.stderr @@ -2,7 +2,7 @@ error[E0277]: `()` cannot be safely transmuted into `W<'_>` in the defining scop --> $DIR/region-infer.rs:20:5 | LL | test(); - | ^^^^ The size of `()` is smaller than the size of `W<'_>` + | ^^^^^^ The size of `()` is smaller than the size of `W<'_>` | note: required by a bound in `test` --> $DIR/region-infer.rs:11:12 diff --git a/tests/ui/type/issue-101866.stderr b/tests/ui/type/issue-101866.stderr index 6f4b380b4e746..4d02153ebe20e 100644 --- a/tests/ui/type/issue-101866.stderr +++ b/tests/ui/type/issue-101866.stderr @@ -5,7 +5,7 @@ LL | fn func(); | ---------- `TraitA::func` defined here ... LL | TraitA::::func(); - | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index ae0a06e6328df..e90784a54ae0d 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -59,7 +59,7 @@ error[E0277]: cannot add `u32` to `i32` --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 | LL | >::add(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add` is not implemented for `i32` = help: the following other types implement trait `Add`: diff --git a/tests/ui/unsized-locals/unsized-exprs.stderr b/tests/ui/unsized-locals/unsized-exprs.stderr index a7f57e3fd1566..8a2ecf0f6c331 100644 --- a/tests/ui/unsized-locals/unsized-exprs.stderr +++ b/tests/ui/unsized-locals/unsized-exprs.stderr @@ -26,7 +26,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation --> $DIR/unsized-exprs.rs:26:22 | LL | udrop::>(A(*foo())); - | ^ doesn't have a size known at compile-time + | ^^^^^^^^^ doesn't have a size known at compile-time | = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` note: required because it appears within the type `A<[u8]>` diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr index 4c15497d5308e..6de4caa76ee0e 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied --> $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())` + | ^^^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())` | help: this trait has no implementations, consider adding one --> $DIR/higher-ranked-fn-type.rs:6:1 diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr index 3318c70f1bb38..4cb3cdd69ad00 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` + | ^^^^^^^^ the trait `for Foo` is not implemented for `fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` | help: this trait has no implementations, consider adding one --> $DIR/higher-ranked-fn-type.rs:6:1 From ef454c4a4a026ebad8ff18cb2d18b17d2ca416a7 Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Wed, 24 Jan 2024 04:56:15 +0000 Subject: [PATCH 188/676] 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 ceaabd38e4186..62bef6d52d994 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -0011fac90d2846ea3c04506238ff6e4ed3ce0efe +f6ee4bf3847277d6d6e2007ff664f8ea0895b11b From a9bc7e99a32fe75bcc3d025ce8d08efb96b97cf9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jan 2024 09:10:40 +0100 Subject: [PATCH 189/676] disable freeBSD tests for now --- src/tools/miri/ci/ci.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 6bcc68ebf7ccd..08fce334e03c2 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -121,8 +121,9 @@ case $HOST_TARGET in MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests # Some targets are only partially supported. - MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align - MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align + # FIXME: freeBSD disabled due to https://github.com/rust-lang/miri/issues/3276 + #MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align + #MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm From cba1fdbff37034776510884c8337f492a8e9ade3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jan 2024 09:37:00 +0100 Subject: [PATCH 190/676] refactor extern static handling --- src/tools/miri/ci/ci.sh | 5 +- src/tools/miri/src/machine.rs | 71 +-------------------- src/tools/miri/src/shims/extern_static.rs | 78 +++++++++++++++++++++++ src/tools/miri/src/shims/mod.rs | 1 + 4 files changed, 82 insertions(+), 73 deletions(-) create mode 100644 src/tools/miri/src/shims/extern_static.rs diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 08fce334e03c2..6bcc68ebf7ccd 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -121,9 +121,8 @@ case $HOST_TARGET in MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests # Some targets are only partially supported. - # FIXME: freeBSD disabled due to https://github.com/rust-lang/miri/issues/3276 - #MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align - #MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align + MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align + MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 4a878f4a36e6c..8aa7c88f1c0be 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -691,7 +691,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { Ok(()) } - fn add_extern_static( + pub(crate) fn add_extern_static( this: &mut MiriInterpCx<'mir, 'tcx>, name: &str, ptr: Pointer>, @@ -701,75 +701,6 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap(); } - fn alloc_extern_static( - this: &mut MiriInterpCx<'mir, 'tcx>, - name: &str, - val: ImmTy<'tcx, Provenance>, - ) -> InterpResult<'tcx> { - let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?; - this.write_immediate(*val, &place)?; - Self::add_extern_static(this, name, place.ptr()); - Ok(()) - } - - /// Sets up the "extern statics" for this machine. - fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { - // "__rust_no_alloc_shim_is_unstable" - let val = ImmTy::from_int(0, this.machine.layouts.u8); - Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?; - - match this.tcx.sess.target.os.as_ref() { - "linux" => { - // "environ" - Self::add_extern_static( - this, - "environ", - this.machine.env_vars.environ.as_ref().unwrap().ptr(), - ); - // A couple zero-initialized pointer-sized extern statics. - // Most of them are for weak symbols, which we all set to null (indicating that the - // symbol is not supported, and triggering fallback code which ends up calling a - // syscall that we do support). - for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"] - { - let val = ImmTy::from_int(0, this.machine.layouts.usize); - Self::alloc_extern_static(this, name, val)?; - } - } - "freebsd" => { - // "environ" - Self::add_extern_static( - this, - "environ", - this.machine.env_vars.environ.as_ref().unwrap().ptr(), - ); - } - "android" => { - // "signal" -- just needs a non-zero pointer value (function does not even get called), - // but we arrange for this to be callable anyway (it will then do nothing). - let layout = this.machine.layouts.const_raw_ptr; - let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal"))); - let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout); - Self::alloc_extern_static(this, "signal", val)?; - // A couple zero-initialized pointer-sized extern statics. - // Most of them are for weak symbols, which we all set to null (indicating that the - // symbol is not supported, and triggering fallback code.) - for name in &["bsd_signal"] { - let val = ImmTy::from_int(0, this.machine.layouts.usize); - Self::alloc_extern_static(this, name, val)?; - } - } - "windows" => { - // "_tls_used" - // This is some obscure hack that is part of the Windows TLS story. It's a `u8`. - let val = ImmTy::from_int(0, this.machine.layouts.u8); - Self::alloc_extern_static(this, "_tls_used", val)?; - } - _ => {} // No "extern statics" supported on this target - } - Ok(()) - } - pub(crate) fn communicate(&self) -> bool { self.isolated_op == IsolatedOp::Allow } diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs new file mode 100644 index 0000000000000..61541a655d215 --- /dev/null +++ b/src/tools/miri/src/shims/extern_static.rs @@ -0,0 +1,78 @@ +//! Provides the `extern static` that this platform expects. + +use crate::*; + +impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { + fn alloc_extern_static( + this: &mut MiriInterpCx<'mir, 'tcx>, + name: &str, + val: ImmTy<'tcx, Provenance>, + ) -> InterpResult<'tcx> { + let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?; + this.write_immediate(*val, &place)?; + Self::add_extern_static(this, name, place.ptr()); + Ok(()) + } + + /// Zero-initialized pointer-sized extern statics are pretty common. + /// Most of them are for weak symbols, which we all set to null (indicating that the + /// symbol is not supported, and triggering fallback code which ends up calling a + /// syscall that we do support). + fn null_ptr_extern_statics( + this: &mut MiriInterpCx<'mir, 'tcx>, + names: &[&str], + ) -> InterpResult<'tcx> { + for name in names { + let val = ImmTy::from_int(0, this.machine.layouts.usize); + Self::alloc_extern_static(this, name, val)?; + } + Ok(()) + } + + /// Sets up the "extern statics" for this machine. + pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + // "__rust_no_alloc_shim_is_unstable" + let val = ImmTy::from_int(0, this.machine.layouts.u8); + Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?; + + match this.tcx.sess.target.os.as_ref() { + "linux" => { + Self::null_ptr_extern_statics( + this, + &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"], + )?; + // "environ" + Self::add_extern_static( + this, + "environ", + this.machine.env_vars.environ.as_ref().unwrap().ptr(), + ); + } + "freebsd" => { + // "environ" + Self::add_extern_static( + this, + "environ", + this.machine.env_vars.environ.as_ref().unwrap().ptr(), + ); + } + "android" => { + Self::null_ptr_extern_statics(this, &["bsd_signal"])?; + // "signal" -- just needs a non-zero pointer value (function does not even get called), + // but we arrange for this to call the `signal` function anyway. + let layout = this.machine.layouts.const_raw_ptr; + let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal"))); + let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout); + Self::alloc_extern_static(this, "signal", val)?; + } + "windows" => { + // "_tls_used" + // This is some obscure hack that is part of the Windows TLS story. It's a `u8`. + let val = ImmTy::from_int(0, this.machine.layouts.u8); + Self::alloc_extern_static(this, "_tls_used", val)?; + } + _ => {} // No "extern statics" supported on this target + } + Ok(()) + } +} diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 1e9d927e1a957..2e0383a5690e0 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -10,6 +10,7 @@ pub mod windows; mod x86; pub mod env; +pub mod extern_static; pub mod os_str; pub mod panic; pub mod time; From e611211f304ef39e326948dd82a7219bf6766cbf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jan 2024 09:37:18 +0100 Subject: [PATCH 191/676] add __cxa_thread_atexit_impl on freebsd --- src/tools/miri/src/shims/extern_static.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs index 61541a655d215..0284e5b606ced 100644 --- a/src/tools/miri/src/shims/extern_static.rs +++ b/src/tools/miri/src/shims/extern_static.rs @@ -49,6 +49,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { ); } "freebsd" => { + Self::null_ptr_extern_statics(this, &["__cxa_thread_atexit_impl"])?; // "environ" Self::add_extern_static( this, From 12dd3bfa2f5280f3ba780fea21a804f721d84014 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jan 2024 10:16:49 +0100 Subject: [PATCH 192/676] a bit of refactoring for find_mir_or_eval_fn --- src/tools/miri/src/lib.rs | 1 - src/tools/miri/src/machine.rs | 16 ++++++++++++- src/tools/miri/src/shims/mod.rs | 41 --------------------------------- 3 files changed, 15 insertions(+), 43 deletions(-) diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index b0b6d9943663f..057b883a3bf9e 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -94,7 +94,6 @@ pub use crate::shims::os_str::EvalContextExt as _; pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _}; pub use crate::shims::time::EvalContextExt as _; pub use crate::shims::tls::TlsData; -pub use crate::shims::EvalContextExt as _; pub use crate::borrow_tracker::stacked_borrows::{ EvalContextExt as _, Item, Permission, Stack, Stacks, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 8aa7c88f1c0be..567ac6cff67c4 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -920,7 +920,21 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { - ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind) + // For foreign items, try to see if we can emulate them. + if ecx.tcx.is_foreign_item(instance.def_id()) { + // An external function call that does not have a MIR body. We either find MIR elsewhere + // or emulate its effect. + // This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need + // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the + // foreign function + // Any needed call to `goto_block` will be performed by `emulate_foreign_item`. + let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? + let link_name = ecx.item_link_name(instance.def_id()); + return ecx.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind); + } + + // Otherwise, load the MIR. + Ok(Some((ecx.load_mir(instance.def, None)?, instance))) } #[inline(always)] diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 2e0383a5690e0..ea6120f757947 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -15,44 +15,3 @@ pub mod os_str; pub mod panic; pub mod time; pub mod tls; - -// End module management, begin local code - -use log::trace; - -use rustc_middle::{mir, ty}; -use rustc_target::spec::abi::Abi; - -use crate::*; - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn find_mir_or_eval_fn( - &mut self, - instance: ty::Instance<'tcx>, - abi: Abi, - args: &[FnArg<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - unwind: mir::UnwindAction, - ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { - let this = self.eval_context_mut(); - trace!("eval_fn_call: {:#?}, {:?}", instance, dest); - - // For foreign items, try to see if we can emulate them. - if this.tcx.is_foreign_item(instance.def_id()) { - // An external function call that does not have a MIR body. We either find MIR elsewhere - // or emulate its effect. - // This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need - // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the - // foreign function - // Any needed call to `goto_block` will be performed by `emulate_foreign_item`. - let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? - let link_name = this.item_link_name(instance.def_id()); - return this.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind); - } - - // Otherwise, load the MIR. - Ok(Some((this.load_mir(instance.def, None)?, instance))) - } -} From 8a850cd12b51507c8a7455c973e54eb14c51696e Mon Sep 17 00:00:00 2001 From: Utkarsh Gupta Date: Wed, 24 Jan 2024 11:10:07 +0000 Subject: [PATCH 193/676] std/time: avoid divisions in Duration::new --- library/core/src/time.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index b677776443fe0..e4f2994296607 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -197,13 +197,18 @@ impl Duration { #[must_use] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn new(secs: u64, nanos: u32) -> Duration { - let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { - Some(secs) => secs, - None => panic!("overflow in Duration::new"), - }; - let nanos = nanos % NANOS_PER_SEC; - // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range - Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + if nanos < NANOS_PER_SEC { + // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + } else { + let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { + Some(secs) => secs, + None => panic!("overflow in Duration::new"), + }; + let nanos = nanos % NANOS_PER_SEC; + // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + } } /// Creates a new `Duration` from the specified number of whole seconds. From e23937c6d32410ef00420c4656d250b4be0064c8 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Wed, 24 Jan 2024 14:57:21 +0000 Subject: [PATCH 194/676] adapt test for v0 symbol mangling No functional changes intended. Adapts the test to also work under new-symbol-mangling = true. --- tests/codegen/infallible-unwrap-in-opt-z.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/infallible-unwrap-in-opt-z.rs b/tests/codegen/infallible-unwrap-in-opt-z.rs index 5c57b41532fbb..e8ab77f8d20de 100644 --- a/tests/codegen/infallible-unwrap-in-opt-z.rs +++ b/tests/codegen/infallible-unwrap-in-opt-z.rs @@ -21,6 +21,6 @@ pub fn read_up_to_8(buf: &[u8]) -> u64 { // CHECK-LABEL: @checking_unwrap_expectation( #[no_mangle] pub fn checking_unwrap_expectation(buf: &[u8]) -> &[u8; 4] { - // CHECK: call void @_ZN4core6result13unwrap_failed17h + // CHECK: call void @{{.*core6result13unwrap_failed}} buf.try_into().unwrap() } From 4780637cbc4b914218753a23ee54f5785826e403 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 21 Jan 2024 04:58:22 +0100 Subject: [PATCH 195/676] suggest similar config option if one is found --- clippy_config/src/conf.rs | 66 +++++++++++++--- clippy_config/src/lib.rs | 1 + tests/ui-toml/toml_unknown_key/clippy.toml | 3 + .../toml_unknown_key/conf_unknown_key.rs | 1 + .../toml_unknown_key/conf_unknown_key.stderr | 79 ++++++++++++++++++- 5 files changed, 137 insertions(+), 13 deletions(-) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 626b23f730999..4e9ddbf8259d3 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -2,7 +2,9 @@ use crate::msrvs::Msrv; use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename}; use crate::ClippyConfiguration; use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; use rustc_session::Session; +use rustc_span::edit_distance::edit_distance; use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext}; use serde::de::{IgnoredAny, IntoDeserializer, MapAccess, Visitor}; use serde::{Deserialize, Deserializer, Serialize}; @@ -59,18 +61,25 @@ impl TryConf { #[derive(Debug)] struct ConfError { message: String, + suggestion: Option, span: Span, } impl ConfError { fn from_toml(file: &SourceFile, error: &toml::de::Error) -> Self { let span = error.span().unwrap_or(0..file.source_len.0 as usize); - Self::spanned(file, error.message(), span) + Self::spanned(file, error.message(), None, span) } - fn spanned(file: &SourceFile, message: impl Into, span: Range) -> Self { + fn spanned( + file: &SourceFile, + message: impl Into, + suggestion: Option, + span: Range, + ) -> Self { Self { message: message.into(), + suggestion, span: Span::new( file.start_pos + BytePos::from_usize(span.start), file.start_pos + BytePos::from_usize(span.end), @@ -147,16 +156,18 @@ macro_rules! define_Conf { match Field::deserialize(name.get_ref().as_str().into_deserializer()) { Err(e) => { let e: FieldError = e; - errors.push(ConfError::spanned(self.0, e.0, name.span())); + errors.push(ConfError::spanned(self.0, e.error, e.suggestion, name.span())); } $(Ok(Field::$name) => { - $(warnings.push(ConfError::spanned(self.0, format!("deprecated field `{}`. {}", name.get_ref(), $dep), name.span()));)? + $(warnings.push(ConfError::spanned(self.0, format!("deprecated field `{}`. {}", name.get_ref(), $dep), None, name.span()));)? let raw_value = map.next_value::>()?; let value_span = raw_value.span(); match <$ty>::deserialize(raw_value.into_inner()) { - Err(e) => errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), value_span)), + Err(e) => errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), None, value_span)), Ok(value) => match $name { - Some(_) => errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), name.span())), + Some(_) => { + errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), None, name.span())); + } None => { $name = Some(value); // $new_conf is the same as one of the defined `$name`s, so @@ -165,7 +176,7 @@ macro_rules! define_Conf { Some(_) => errors.push(ConfError::spanned(self.0, concat!( "duplicate field `", stringify!($new_conf), "` (provided as `", stringify!($name), "`)" - ), name.span())), + ), None, name.span())), None => $new_conf = $name.clone(), })? }, @@ -673,10 +684,16 @@ impl Conf { // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { - sess.dcx().span_err( + let mut diag = sess.dcx().struct_span_err( error.span, format!("error reading Clippy's configuration file: {}", error.message), ); + + if let Some(sugg) = error.suggestion { + diag.span_suggestion(error.span, sugg.message, sugg.suggestion, Applicability::MaybeIncorrect); + } + + diag.emit(); } for warning in warnings { @@ -693,19 +710,31 @@ impl Conf { const SEPARATOR_WIDTH: usize = 4; #[derive(Debug)] -struct FieldError(String); +struct FieldError { + error: String, + suggestion: Option, +} + +#[derive(Debug)] +struct Suggestion { + message: &'static str, + suggestion: &'static str, +} impl std::error::Error for FieldError {} impl Display for FieldError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.pad(&self.0) + f.pad(&self.error) } } impl serde::de::Error for FieldError { fn custom(msg: T) -> Self { - Self(msg.to_string()) + Self { + error: msg.to_string(), + suggestion: None, + } } fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { @@ -727,7 +756,20 @@ impl serde::de::Error for FieldError { write!(msg, "{:SEPARATOR_WIDTH$}{field:column_width$}", " ").unwrap(); } } - Self(msg) + + let suggestion = expected + .iter() + .filter_map(|expected| { + let dist = edit_distance(field, expected, 4)?; + Some((dist, expected)) + }) + .min_by_key(|&(dist, _)| dist) + .map(|(_, suggestion)| Suggestion { + message: "perhaps you meant", + suggestion, + }); + + Self { error: msg, suggestion } } } diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index f5dcb16d670df..533e375a3104c 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -11,6 +11,7 @@ extern crate rustc_ast; extern crate rustc_data_structures; #[allow(unused_extern_crates)] extern crate rustc_driver; +extern crate rustc_errors; extern crate rustc_session; extern crate rustc_span; diff --git a/tests/ui-toml/toml_unknown_key/clippy.toml b/tests/ui-toml/toml_unknown_key/clippy.toml index b77b4580051ef..2b63f6e5c26f7 100644 --- a/tests/ui-toml/toml_unknown_key/clippy.toml +++ b/tests/ui-toml/toml_unknown_key/clippy.toml @@ -3,6 +3,9 @@ foobar = 42 # so is this one barfoo = 53 +# when using underscores instead of dashes, suggest the correct one +allow_mixed_uninlined_format_args = true + # that one is ignored [third-party] clippy-feature = "nightly" diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs index 38009627757c2..49139b60a9f43 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -1,3 +1,4 @@ +//@no-rustfix //@error-in-other-file: unknown field `foobar`, expected one of fn main() {} diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 09fc9dfa463eb..fc683e514ba40 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -152,5 +152,82 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect LL | barfoo = 53 | ^^^^^^ -error: aborting due to 2 previous errors +error: error reading Clippy's configuration file: unknown field `allow_mixed_uninlined_format_args`, expected one of + absolute-paths-allowed-crates + absolute-paths-max-segments + accept-comment-above-attributes + accept-comment-above-statement + allow-dbg-in-tests + allow-expect-in-tests + allow-mixed-uninlined-format-args + allow-one-hash-in-raw-strings + allow-print-in-tests + allow-private-module-inception + allow-unwrap-in-tests + allowed-dotfiles + allowed-duplicate-crates + allowed-idents-below-min-chars + allowed-scripts + arithmetic-side-effects-allowed + arithmetic-side-effects-allowed-binary + arithmetic-side-effects-allowed-unary + array-size-threshold + avoid-breaking-exported-api + await-holding-invalid-types + blacklisted-names + cargo-ignore-publish + check-private-items + cognitive-complexity-threshold + cyclomatic-complexity-threshold + disallowed-macros + disallowed-methods + disallowed-names + disallowed-types + doc-valid-idents + enable-raw-pointer-heuristic-for-send + enforce-iter-loop-reborrow + enforced-import-renames + enum-variant-name-threshold + enum-variant-size-threshold + excessive-nesting-threshold + future-size-threshold + ignore-interior-mutability + large-error-threshold + literal-representation-threshold + matches-for-let-else + max-fn-params-bools + max-include-file-size + max-struct-bools + max-suggested-slice-pattern-length + max-trait-bounds + min-ident-chars-threshold + missing-docs-in-crate-items + msrv + pass-by-value-size-limit + pub-underscore-fields-behavior + semicolon-inside-block-ignore-singleline + semicolon-outside-block-ignore-multiline + single-char-binding-names-threshold + stack-size-threshold + standard-macro-braces + struct-field-name-threshold + suppress-restriction-lint-in-const + third-party + too-large-for-stack + too-many-arguments-threshold + too-many-lines-threshold + trivial-copy-size-limit + type-complexity-threshold + unnecessary-box-size + unreadable-literal-lint-fractions + upper-case-acronyms-aggressive + vec-box-size-threshold + verbose-bit-mask-threshold + warn-on-all-wildcard-imports + --> $DIR/$DIR/clippy.toml:7:1 + | +LL | allow_mixed_uninlined_format_args = true + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: perhaps you meant: `allow-mixed-uninlined-format-args` + +error: aborting due to 3 previous errors From 314dbc7f2250cc7bece306254f6bfafc96bf913f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 22 Jan 2024 16:58:39 +1100 Subject: [PATCH 196/676] Avoid useless checking in `from_token_lit`. The parser already does a check-only unescaping which catches all errors. So the checking done in `from_token_lit` never hits. But literals causing warnings can still occur in `from_token_lit`. So the commit changes `str-escape.rs` to use byte string literals and C string literals as well, to give better coverage and ensure the new assertions in `from_token_lit` are correct. --- compiler/rustc_ast/src/util/literal.rs | 83 +++++++------------------- tests/ui/str/str-escape.rs | 9 +-- tests/ui/str/str-escape.stderr | 14 ++--- 3 files changed, 33 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 7b781ba1e1121..852d49fc5b628 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -48,6 +48,9 @@ impl LitKind { return Err(LitError::InvalidSuffix); } + // For byte/char/string literals, chars and escapes have already been + // checked in the lexer (in `cook_lexer_literal`). So we can assume all + // chars and escapes are valid here. Ok(match kind { token::Bool => { assert!(symbol.is_bool_lit()); @@ -56,12 +59,12 @@ impl LitKind { token::Byte => { return unescape_byte(symbol.as_str()) .map(LitKind::Byte) - .map_err(|_| LitError::LexerError); + .map_err(|_| panic!("failed to unescape byte literal")); } token::Char => { return unescape_char(symbol.as_str()) .map(LitKind::Char) - .map_err(|_| LitError::LexerError); + .map_err(|_| panic!("failed to unescape char literal")); } // There are some valid suffixes for integer and float literals, @@ -77,26 +80,22 @@ impl LitKind { let s = symbol.as_str(); // Vanilla strings are so common we optimize for the common case where no chars // requiring special behaviour are present. - let symbol = if s.contains(['\\', '\r']) { + let symbol = if s.contains('\\') { let mut buf = String::with_capacity(s.len()); - let mut error = Ok(()); // Force-inlining here is aggressive but the closure is - // called on every char in the string, so it can be - // hot in programs with many long strings. + // called on every char in the string, so it can be hot in + // programs with many long strings containing escapes. unescape_literal( s, Mode::Str, &mut #[inline(always)] - |_, unescaped_char| match unescaped_char { + |_, c| match c { Ok(c) => buf.push(c), Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + assert!(!err.is_fatal(), "failed to unescape string literal") } }, ); - error?; Symbol::intern(&buf) } else { symbol @@ -104,86 +103,46 @@ impl LitKind { LitKind::Str(symbol, ast::StrStyle::Cooked) } token::StrRaw(n) => { - // Raw strings have no escapes, so we only need to check for invalid chars, and we - // can reuse the symbol on success. - let mut error = Ok(()); - unescape_literal(symbol.as_str(), Mode::RawStr, &mut |_, unescaped_char| { - match unescaped_char { - Ok(_) => {} - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } - } - } - }); - error?; + // Raw strings have no escapes so no work is needed here. LitKind::Str(symbol, ast::StrStyle::Raw(n)) } token::ByteStr => { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); - let mut error = Ok(()); unescape_literal(s, Mode::ByteStr, &mut |_, c| match c { Ok(c) => buf.push(byte_from_char(c)), Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + assert!(!err.is_fatal(), "failed to unescape string literal") } }); - error?; LitKind::ByteStr(buf.into(), StrStyle::Cooked) } token::ByteStrRaw(n) => { - // Raw strings have no escapes, so we only need to check for invalid chars, and we - // can convert the symbol directly to a `Lrc` on success. - let s = symbol.as_str(); - let mut error = Ok(()); - unescape_literal(s, Mode::RawByteStr, &mut |_, c| match c { - Ok(_) => {} - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } - } - }); - LitKind::ByteStr(s.to_owned().into_bytes().into(), StrStyle::Raw(n)) + // Raw strings have no escapes so we can convert the symbol + // directly to a `Lrc`. + let buf = symbol.as_str().to_owned().into_bytes(); + LitKind::ByteStr(buf.into(), StrStyle::Raw(n)) } token::CStr => { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); - let mut error = Ok(()); unescape_c_string(s, Mode::CStr, &mut |_span, c| match c { Ok(CStrUnit::Byte(b)) => buf.push(b), Ok(CStrUnit::Char(c)) => { buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) } Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + assert!(!err.is_fatal(), "failed to unescape C string literal") } }); - error?; buf.push(0); LitKind::CStr(buf.into(), StrStyle::Cooked) } token::CStrRaw(n) => { - // Raw strings have no escapes, so we only need to check for invalid chars, and we - // can convert the symbol directly to a `Lrc` on success. - let s = symbol.as_str(); - let mut error = Ok(()); - unescape_c_string(s, Mode::RawCStr, &mut |_, c| match c { - Ok(_) => {} - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } - } - }); - error?; - let mut buf = s.to_owned().into_bytes(); + // Raw strings have no escapes so we can convert the symbol + // directly to a `Lrc` after appending the terminating NUL + // char. + let mut buf = symbol.as_str().to_owned().into_bytes(); buf.push(0); LitKind::CStr(buf.into(), StrStyle::Raw(n)) } diff --git a/tests/ui/str/str-escape.rs b/tests/ui/str/str-escape.rs index 10a72421f24a7..89a8217106391 100644 --- a/tests/ui/str/str-escape.rs +++ b/tests/ui/str/str-escape.rs @@ -1,5 +1,6 @@ // check-pass // ignore-tidy-tab +// edition: 2021 fn main() { let s = "\ @@ -8,11 +9,11 @@ fn main() { //~^^^ WARNING multiple lines skipped by escaped newline assert_eq!(s, ""); - let s = "foo\ + let s = c"foo\   bar "; //~^^^ WARNING whitespace symbol '\u{a0}' is not skipped - assert_eq!(s, "foo  bar\n "); + assert_eq!(s, c"foo  bar\n "); let s = "a\ b"; @@ -22,10 +23,10 @@ fn main() { b"; assert_eq!(s, "ab"); - let s = "a\ + let s = b"a\ b"; //~^^ WARNING whitespace symbol '\u{c}' is not skipped // '\x0c' is ASCII whitespace, but it may not need skipped // discussion: https://github.com/rust-lang/rust/pull/108403 - assert_eq!(s, "a\x0cb"); + assert_eq!(s, b"a\x0cb"); } diff --git a/tests/ui/str/str-escape.stderr b/tests/ui/str/str-escape.stderr index 43b4f7e36f6ab..00fe5444e1a4e 100644 --- a/tests/ui/str/str-escape.stderr +++ b/tests/ui/str/str-escape.stderr @@ -1,5 +1,5 @@ warning: multiple lines skipped by escaped newline - --> $DIR/str-escape.rs:5:14 + --> $DIR/str-escape.rs:6:14 | LL | let s = "\ | ______________^ @@ -8,20 +8,20 @@ LL | | "; | |_____________^ skipping everything up to and including this point warning: whitespace symbol '\u{a0}' is not skipped - --> $DIR/str-escape.rs:11:17 + --> $DIR/str-escape.rs:12:18 | -LL | let s = "foo\ - | _________________^ +LL | let s = c"foo\ + | __________________^ LL | |   bar | | ^ whitespace symbol '\u{a0}' is not skipped | |___| | warning: whitespace symbol '\u{c}' is not skipped - --> $DIR/str-escape.rs:25:15 + --> $DIR/str-escape.rs:26:16 | -LL | let s = "a\ - | _______________^ +LL | let s = b"a\ + | ________________^ LL | | b"; | | ^- whitespace symbol '\u{c}' is not skipped | |____| From 4b4bdb575b8498b22729a522885ffadd0e646c0f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 24 Jan 2024 16:46:57 +1100 Subject: [PATCH 197/676] Fix copy/paste error. The `CString` handling code is erroneously identical to the `ByteString` handling code. --- src/tools/rust-analyzer/crates/syntax/src/validation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 69dffbf79f191..fadcbaef14330 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{self, unescape_literal, Mode}; +use rustc_lexer::unescape::{self, unescape_c_string, unescape_literal, Mode}; use crate::{ algo, @@ -162,7 +162,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::CString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { + unescape_c_string(without_quotes, Mode::CStr, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } From 85d56eeb63493c2b707883fb842b4fe40396beae Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 24 Jan 2024 16:46:57 +1100 Subject: [PATCH 198/676] Fix copy/paste error. The `CString` handling code is erroneously identical to the `ByteString` handling code. --- crates/syntax/src/validation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 69dffbf79f191..fadcbaef14330 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{self, unescape_literal, Mode}; +use rustc_lexer::unescape::{self, unescape_c_string, unescape_literal, Mode}; use crate::{ algo, @@ -162,7 +162,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::CString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { + unescape_c_string(without_quotes, Mode::CStr, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } From ef1e2228cfd9df4059aa44740b0659fea7c5a52f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 23 Jan 2024 10:37:27 +1100 Subject: [PATCH 199/676] Use `from` instead of `into` in unescaping code. The `T` type in these functions took me some time to understand, and I find the explicit `T` in the use of `from` makes the code easier to read, as does the `u8` annotation in `scan_escape`. --- compiler/rustc_lexer/src/unescape.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 0a632c4d12ad5..a5ab3fcdd34a0 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -222,7 +222,7 @@ fn scan_escape + From>( mode: Mode, ) -> Result { // Previous character was '\\', unescape what follows. - let res = match chars.next().ok_or(EscapeError::LoneSlash)? { + let res: u8 = match chars.next().ok_or(EscapeError::LoneSlash)? { '"' => b'"', 'n' => b'\n', 'r' => b'\r', @@ -249,10 +249,10 @@ fn scan_escape + From>( value as u8 } - 'u' => return scan_unicode(chars, mode.is_unicode_escape_disallowed()).map(Into::into), + 'u' => return scan_unicode(chars, mode.is_unicode_escape_disallowed()).map(T::from), _ => return Err(EscapeError::InvalidEscape), }; - Ok(res.into()) + Ok(T::from(res)) } fn scan_unicode( @@ -366,7 +366,7 @@ where } '"' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(c, chars_should_be_ascii).map(Into::into), + _ => ascii_check(c, chars_should_be_ascii).map(T::from), }; let end = src.len() - chars.as_str().len(); callback(start..end, res); From a1c07214f0f7988cbc5a645a499bb8f7dd9cbed7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 23 Jan 2024 12:27:56 +1100 Subject: [PATCH 200/676] Rework `CStrUnit`. - Rename it as `MixedUnit`, because it will soon be used in more than just C string literals. - Change the `Byte` variant to `HighByte` and use it only for `\x80`..`\xff` cases. This fixes the old inexactness where ASCII chars could be encoded with either `Byte` or `Char`. - Add useful comments. - Remove `is_ascii`, in favour of `u8::is_ascii`. --- compiler/rustc_ast/src/util/literal.rs | 6 +- compiler/rustc_lexer/src/unescape.rs | 79 +++++++++++-------- .../crates/syntax/src/ast/token_ext.rs | 9 +-- 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 852d49fc5b628..c3995c7776f94 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -3,7 +3,7 @@ use crate::ast::{self, LitKind, MetaItemLit, StrStyle}; use crate::token::{self, Token}; use rustc_lexer::unescape::{ - byte_from_char, unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, + byte_from_char, unescape_byte, unescape_c_string, unescape_char, unescape_literal, MixedUnit, Mode, }; use rustc_span::symbol::{kw, sym, Symbol}; @@ -127,10 +127,10 @@ impl LitKind { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); unescape_c_string(s, Mode::CStr, &mut |_span, c| match c { - Ok(CStrUnit::Byte(b)) => buf.push(b), - Ok(CStrUnit::Char(c)) => { + Ok(MixedUnit::Char(c)) => { buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) } + Ok(MixedUnit::HighByte(b)) => buf.push(b), Err(err) => { assert!(!err.is_fatal(), "failed to unescape C string literal") } diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index a5ab3fcdd34a0..3c23af58f376a 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -101,32 +101,45 @@ where } } -/// A unit within CStr. Must not be a nul character. -pub enum CStrUnit { - Byte(u8), +/// Used for mixed utf8 string literals, i.e. those that allow both unicode +/// chars and high bytes. +pub enum MixedUnit { + /// Used for ASCII chars (written directly or via `\x00`..`\x7f` escapes) + /// and Unicode chars (written directly or via `\u` escapes). + /// + /// For example, if '¥' appears in a string it is represented here as + /// `MixedUnit::Char('¥')`, and it will be appended to the relevant byte + /// string as the two-byte UTF-8 sequence `[0xc2, 0xa5]` Char(char), + + /// Used for high bytes (`\x80`..`\xff`). + /// + /// For example, if `\xa5` appears in a string it is represented here as + /// `MixedUnit::HighByte(0xa5)`, and it will be appended to the relevant + /// byte string as the single byte `0xa5`. + HighByte(u8), } -impl From for CStrUnit { - fn from(value: u8) -> Self { - CStrUnit::Byte(value) +impl From for MixedUnit { + fn from(c: char) -> Self { + MixedUnit::Char(c) } } -impl From for CStrUnit { - fn from(value: char) -> Self { - CStrUnit::Char(value) +impl From for MixedUnit { + fn from(n: u8) -> Self { + if n.is_ascii() { MixedUnit::Char(n as char) } else { MixedUnit::HighByte(n) } } } pub fn unescape_c_string(src: &str, mode: Mode, callback: &mut F) where - F: FnMut(Range, Result), + F: FnMut(Range, Result), { match mode { CStr => { unescape_non_raw_common(src, mode, &mut |r, mut result| { - if let Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) = result { + if let Ok(MixedUnit::Char('\0')) = result { result = Err(EscapeError::NulInCStr); } callback(r, result) @@ -137,7 +150,8 @@ where if let Ok('\0') = result { result = Err(EscapeError::NulInCStr); } - callback(r, result.map(CStrUnit::Char)) + // High bytes aren't possible in raw strings. + callback(r, result.map(MixedUnit::Char)) }); } Char | Byte | Str | RawStr | ByteStr | RawByteStr => unreachable!(), @@ -217,20 +231,19 @@ impl Mode { } } -fn scan_escape + From>( +fn scan_escape + From>( chars: &mut Chars<'_>, mode: Mode, ) -> Result { // Previous character was '\\', unescape what follows. - let res: u8 = match chars.next().ok_or(EscapeError::LoneSlash)? { - '"' => b'"', - 'n' => b'\n', - 'r' => b'\r', - 't' => b'\t', - '\\' => b'\\', - '\'' => b'\'', - '0' => b'\0', - + let res: char = match chars.next().ok_or(EscapeError::LoneSlash)? { + '"' => '"', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + '\\' => '\\', + '\'' => '\'', + '0' => '\0', 'x' => { // Parse hexadecimal character code. @@ -240,15 +253,17 @@ fn scan_escape + From>( let lo = chars.next().ok_or(EscapeError::TooShortHexEscape)?; let lo = lo.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?; - let value = hi * 16 + lo; - - if mode.ascii_escapes_should_be_ascii() && !is_ascii(value) { - return Err(EscapeError::OutOfRangeHexEscape); - } + let value = (hi * 16 + lo) as u8; - value as u8 + return if mode.ascii_escapes_should_be_ascii() && !value.is_ascii() { + Err(EscapeError::OutOfRangeHexEscape) + } else { + // This may be a high byte, but that will only happen if `T` is + // `MixedUnit`, because of the `ascii_escapes_should_be_ascii` + // check above. + Ok(T::from(value as u8)) + }; } - 'u' => return scan_unicode(chars, mode.is_unicode_escape_disallowed()).map(T::from), _ => return Err(EscapeError::InvalidEscape), }; @@ -336,7 +351,7 @@ fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result + From>(src: &str, mode: Mode, callback: &mut F) +fn unescape_non_raw_common + From>(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { @@ -430,7 +445,3 @@ pub fn byte_from_char(c: char) -> u8 { debug_assert!(res <= u8::MAX as u32, "guaranteed because of ByteStr"); res as u8 } - -fn is_ascii(x: u32) -> bool { - x <= 0x7F -} diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs index b39006e2ff265..2f75e9677ec89 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs @@ -6,7 +6,7 @@ use std::{ }; use rustc_lexer::unescape::{ - unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode, + unescape_byte, unescape_c_string, unescape_char, unescape_literal, MixedUnit, Mode, }; use crate::{ @@ -336,10 +336,9 @@ impl ast::CString { let mut buf = Vec::new(); let mut prev_end = 0; let mut has_error = false; - let mut char_buf = [0u8; 4]; - let mut extend_unit = |buf: &mut Vec, unit: CStrUnit| match unit { - CStrUnit::Byte(b) => buf.push(b), - CStrUnit::Char(c) => buf.extend(c.encode_utf8(&mut char_buf).as_bytes()), + let extend_unit = |buf: &mut Vec, unit: MixedUnit| match unit { + MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()), + MixedUnit::HighByte(b) => buf.push(b), }; unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match ( unescaped, From 5e5aa6d556c273141a37c8cb542a022e3e9fae67 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 23 Jan 2024 14:25:34 +1100 Subject: [PATCH 201/676] Rename and invert sense of `Mode` predicates. I find it easier if they describe what's allowed, rather than what's forbidden. Also, consistent naming makes them easier to understand. --- compiler/rustc_lexer/src/unescape.rs | 56 ++++++++++++---------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 3c23af58f376a..e4cf7439b97da 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -195,29 +195,29 @@ impl Mode { } } - /// Non-byte literals should have `\xXX` escapes that are within the ASCII range. - fn ascii_escapes_should_be_ascii(self) -> bool { + /// Are `\x80`..`\xff` allowed? + fn allow_high_bytes(self) -> bool { match self { - Char | Str => true, - Byte | ByteStr | CStr => false, + Char | Str => false, + Byte | ByteStr | CStr => true, RawStr | RawByteStr | RawCStr => unreachable!(), } } - /// Whether characters within the literal must be within the ASCII range. + /// Are unicode (non-ASCII) chars allowed? #[inline] - fn chars_should_be_ascii(self) -> bool { + fn allow_unicode_chars(self) -> bool { match self { - Byte | ByteStr | RawByteStr => true, - Char | Str | RawStr | CStr | RawCStr => false, + Byte | ByteStr | RawByteStr => false, + Char | Str | RawStr | CStr | RawCStr => true, } } - /// Byte literals do not allow unicode escape. - fn is_unicode_escape_disallowed(self) -> bool { + /// Are unicode escapes (`\u`) allowed? + fn allow_unicode_escapes(self) -> bool { match self { - Byte | ByteStr => true, - Char | Str | CStr => false, + Byte | ByteStr => false, + Char | Str | CStr => true, RawByteStr | RawStr | RawCStr => unreachable!(), } } @@ -255,25 +255,21 @@ fn scan_escape + From>( let value = (hi * 16 + lo) as u8; - return if mode.ascii_escapes_should_be_ascii() && !value.is_ascii() { + return if !mode.allow_high_bytes() && !value.is_ascii() { Err(EscapeError::OutOfRangeHexEscape) } else { // This may be a high byte, but that will only happen if `T` is - // `MixedUnit`, because of the `ascii_escapes_should_be_ascii` - // check above. + // `MixedUnit`, because of the `allow_high_bytes` check above. Ok(T::from(value as u8)) }; } - 'u' => return scan_unicode(chars, mode.is_unicode_escape_disallowed()).map(T::from), + 'u' => return scan_unicode(chars, mode.allow_unicode_escapes()).map(T::from), _ => return Err(EscapeError::InvalidEscape), }; Ok(T::from(res)) } -fn scan_unicode( - chars: &mut Chars<'_>, - is_unicode_escape_disallowed: bool, -) -> Result { +fn scan_unicode(chars: &mut Chars<'_>, allow_unicode_escapes: bool) -> Result { // We've parsed '\u', now we have to parse '{..}'. if chars.next() != Some('{') { @@ -301,7 +297,7 @@ fn scan_unicode( // Incorrect syntax has higher priority for error reporting // than unallowed value for a literal. - if is_unicode_escape_disallowed { + if !allow_unicode_escapes { return Err(EscapeError::UnicodeEscapeInByte); } @@ -327,12 +323,8 @@ fn scan_unicode( } #[inline] -fn ascii_check(c: char, chars_should_be_ascii: bool) -> Result { - if chars_should_be_ascii && !c.is_ascii() { - Err(EscapeError::NonAsciiCharInByte) - } else { - Ok(c) - } +fn ascii_check(c: char, allow_unicode_chars: bool) -> Result { + if allow_unicode_chars || c.is_ascii() { Ok(c) } else { Err(EscapeError::NonAsciiCharInByte) } } fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result { @@ -341,7 +333,7 @@ fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result scan_escape(chars, mode), '\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(c, mode.chars_should_be_ascii()), + _ => ascii_check(c, mode.allow_unicode_chars()), }?; if chars.next().is_some() { return Err(EscapeError::MoreThanOneChar); @@ -356,7 +348,7 @@ where F: FnMut(Range, Result), { let mut chars = src.chars(); - let chars_should_be_ascii = mode.chars_should_be_ascii(); // get this outside the loop + let allow_unicode_chars = mode.allow_unicode_chars(); // get this outside the loop // The `start` and `end` computation here is complicated because // `skip_ascii_whitespace` makes us to skip over chars without counting @@ -381,7 +373,7 @@ where } '"' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(c, chars_should_be_ascii).map(T::from), + _ => ascii_check(c, allow_unicode_chars).map(T::from), }; let end = src.len() - chars.as_str().len(); callback(start..end, res); @@ -423,7 +415,7 @@ where F: FnMut(Range, Result), { let mut chars = src.chars(); - let chars_should_be_ascii = mode.chars_should_be_ascii(); // get this outside the loop + let allow_unicode_chars = mode.allow_unicode_chars(); // get this outside the loop // The `start` and `end` computation here matches the one in // `unescape_non_raw_common` for consistency, even though this function @@ -432,7 +424,7 @@ where let start = src.len() - chars.as_str().len() - c.len_utf8(); let res = match c { '\r' => Err(EscapeError::BareCarriageReturnInRawString), - _ => ascii_check(c, chars_should_be_ascii), + _ => ascii_check(c, allow_unicode_chars), }; let end = src.len() - chars.as_str().len(); callback(start..end, res); From 86f371ed59e4172c9891bc9b976362a73689fb12 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 24 Jan 2024 15:24:58 +1100 Subject: [PATCH 202/676] Rename the unescaping functions. `unescape_literal` becomes `unescape_unicode`, and `unescape_c_string` becomes `unescape_mixed`. Because rfc3349 will mean that C string literals will no longer be the only mixed utf8 literals. --- compiler/rustc_ast/src/util/literal.rs | 9 ++++--- compiler/rustc_lexer/src/unescape.rs | 12 ++++++---- compiler/rustc_lexer/src/unescape/tests.rs | 10 ++++---- compiler/rustc_parse/src/lexer/mod.rs | 24 +++++++++---------- compiler/rustc_parse_format/src/lib.rs | 2 +- .../clippy/clippy_dev/src/update_lints.rs | 2 +- .../crates/parser/src/lexed_str.rs | 4 ++-- .../crates/syntax/src/ast/token_ext.rs | 12 +++++----- .../crates/syntax/src/validation.rs | 12 +++++----- 9 files changed, 45 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index c3995c7776f94..aaeb1bb9bff82 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -3,8 +3,7 @@ use crate::ast::{self, LitKind, MetaItemLit, StrStyle}; use crate::token::{self, Token}; use rustc_lexer::unescape::{ - byte_from_char, unescape_byte, unescape_c_string, unescape_char, unescape_literal, MixedUnit, - Mode, + byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode, }; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; @@ -85,7 +84,7 @@ impl LitKind { // Force-inlining here is aggressive but the closure is // called on every char in the string, so it can be hot in // programs with many long strings containing escapes. - unescape_literal( + unescape_unicode( s, Mode::Str, &mut #[inline(always)] @@ -109,7 +108,7 @@ impl LitKind { token::ByteStr => { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); - unescape_literal(s, Mode::ByteStr, &mut |_, c| match c { + unescape_unicode(s, Mode::ByteStr, &mut |_, c| match c { Ok(c) => buf.push(byte_from_char(c)), Err(err) => { assert!(!err.is_fatal(), "failed to unescape string literal") @@ -126,7 +125,7 @@ impl LitKind { token::CStr => { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); - unescape_c_string(s, Mode::CStr, &mut |_span, c| match c { + unescape_mixed(s, Mode::CStr, &mut |_span, c| match c { Ok(MixedUnit::Char(c)) => { buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) } diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index e4cf7439b97da..4da6d35727cb5 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -80,12 +80,12 @@ impl EscapeError { } } -/// Takes a contents of a literal (without quotes) and produces a sequence of -/// escaped characters or errors. +/// Takes the contents of a unicode-only (non-mixed-utf8) literal (without +/// quotes) and produces a sequence of escaped characters or errors. /// /// Values are returned by invoking `callback`. For `Char` and `Byte` modes, /// the callback will be called exactly once. -pub fn unescape_literal(src: &str, mode: Mode, callback: &mut F) +pub fn unescape_unicode(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { @@ -132,7 +132,11 @@ impl From for MixedUnit { } } -pub fn unescape_c_string(src: &str, mode: Mode, callback: &mut F) +/// Takes the contents of a mixed-utf8 literal (without quotes) and produces +/// a sequence of escaped characters or errors. +/// +/// Values are returned by invoking `callback`. +pub fn unescape_mixed(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs index 1c25b03fdb22e..5b99495f47581 100644 --- a/compiler/rustc_lexer/src/unescape/tests.rs +++ b/compiler/rustc_lexer/src/unescape/tests.rs @@ -100,7 +100,7 @@ fn test_unescape_char_good() { fn test_unescape_str_warn() { fn check(literal: &str, expected: &[(Range, Result)]) { let mut unescaped = Vec::with_capacity(literal.len()); - unescape_literal(literal, Mode::Str, &mut |range, res| unescaped.push((range, res))); + unescape_unicode(literal, Mode::Str, &mut |range, res| unescaped.push((range, res))); assert_eq!(unescaped, expected); } @@ -124,7 +124,7 @@ fn test_unescape_str_warn() { fn test_unescape_str_good() { fn check(literal_text: &str, expected: &str) { let mut buf = Ok(String::with_capacity(literal_text.len())); - unescape_literal(literal_text, Mode::Str, &mut |range, c| { + unescape_unicode(literal_text, Mode::Str, &mut |range, c| { if let Ok(b) = &mut buf { match c { Ok(c) => b.push(c), @@ -241,7 +241,7 @@ fn test_unescape_byte_good() { fn test_unescape_byte_str_good() { fn check(literal_text: &str, expected: &[u8]) { let mut buf = Ok(Vec::with_capacity(literal_text.len())); - unescape_literal(literal_text, Mode::ByteStr, &mut |range, c| { + unescape_unicode(literal_text, Mode::ByteStr, &mut |range, c| { if let Ok(b) = &mut buf { match c { Ok(c) => b.push(byte_from_char(c)), @@ -264,7 +264,7 @@ fn test_unescape_byte_str_good() { fn test_unescape_raw_str() { fn check(literal: &str, expected: &[(Range, Result)]) { let mut unescaped = Vec::with_capacity(literal.len()); - unescape_literal(literal, Mode::RawStr, &mut |range, res| unescaped.push((range, res))); + unescape_unicode(literal, Mode::RawStr, &mut |range, res| unescaped.push((range, res))); assert_eq!(unescaped, expected); } @@ -276,7 +276,7 @@ fn test_unescape_raw_str() { fn test_unescape_raw_byte_str() { fn check(literal: &str, expected: &[(Range, Result)]) { let mut unescaped = Vec::with_capacity(literal.len()); - unescape_literal(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res))); + unescape_unicode(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res))); assert_eq!(unescaped, expected); } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index d7ecf577ed676..a491d1969bd5c 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -400,7 +400,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { .with_code(error_code!(E0762)) .emit() } - self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' ' + self.cook_unicode(token::Char, Mode::Char, start, end, 1, 1) // ' ' } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { @@ -412,7 +412,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { .with_code(error_code!(E0763)) .emit() } - self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' ' + self.cook_unicode(token::Byte, Mode::Byte, start, end, 2, 1) // b' ' } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { @@ -424,7 +424,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { .with_code(error_code!(E0765)) .emit() } - self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " " + self.cook_unicode(token::Str, Mode::Str, start, end, 1, 1) // " " } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { @@ -436,7 +436,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { .with_code(error_code!(E0766)) .emit() } - self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" " + self.cook_unicode(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" " } rustc_lexer::LiteralKind::CStr { terminated } => { if !terminated { @@ -448,13 +448,13 @@ impl<'sess, 'src> StringReader<'sess, 'src> { .with_code(error_code!(E0767)) .emit() } - self.cook_c_string(token::CStr, Mode::CStr, start, end, 2, 1) // c" " + self.cook_mixed(token::CStr, Mode::CStr, start, end, 2, 1) // c" " } rustc_lexer::LiteralKind::RawStr { n_hashes } => { if let Some(n_hashes) = n_hashes { let n = u32::from(n_hashes); let kind = token::StrRaw(n_hashes); - self.cook_quoted(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "## + self.cook_unicode(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "## } else { self.report_raw_str_error(start, 1); } @@ -463,7 +463,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { if let Some(n_hashes) = n_hashes { let n = u32::from(n_hashes); let kind = token::ByteStrRaw(n_hashes); - self.cook_quoted(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "## + self.cook_unicode(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "## } else { self.report_raw_str_error(start, 2); } @@ -472,7 +472,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { if let Some(n_hashes) = n_hashes { let n = u32::from(n_hashes); let kind = token::CStrRaw(n_hashes); - self.cook_c_string(kind, Mode::RawCStr, start, end, 3 + n, 1 + n) // cr##" "## + self.cook_mixed(kind, Mode::RawCStr, start, end, 3 + n, 1 + n) // cr##" "## } else { self.report_raw_str_error(start, 2); } @@ -735,7 +735,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { } } - fn cook_quoted( + fn cook_unicode( &self, kind: token::LitKind, mode: Mode, @@ -745,13 +745,13 @@ impl<'sess, 'src> StringReader<'sess, 'src> { postfix_len: u32, ) -> (token::LitKind, Symbol) { self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| { - unescape::unescape_literal(src, mode, &mut |span, result| { + unescape::unescape_unicode(src, mode, &mut |span, result| { callback(span, result.map(drop)) }) }) } - fn cook_c_string( + fn cook_mixed( &self, kind: token::LitKind, mode: Mode, @@ -761,7 +761,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { postfix_len: u32, ) -> (token::LitKind, Symbol) { self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| { - unescape::unescape_c_string(src, mode, &mut |span, result| { + unescape::unescape_mixed(src, mode, &mut |span, result| { callback(span, result.map(drop)) }) }) diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 625764876a6b6..d76ee161da6fd 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -1056,7 +1056,7 @@ fn find_width_map_from_snippet( fn unescape_string(string: &str) -> Option { let mut buf = string::String::new(); let mut ok = true; - unescape::unescape_literal(string, unescape::Mode::Str, &mut |_, unescaped_char| { + unescape::unescape_unicode(string, unescape::Mode::Str, &mut |_, unescaped_char| { match unescaped_char { Ok(c) => buf.push(c), Err(_) => ok = false, diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index 6b76a44debff7..f598f5d3d50f8 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -928,7 +928,7 @@ fn remove_line_splices(s: &str) -> String { .and_then(|s| s.strip_suffix('"')) .unwrap_or_else(|| panic!("expected quoted string, found `{s}`")); let mut res = String::with_capacity(s.len()); - unescape::unescape_literal(s, unescape::Mode::Str, &mut |range, ch| { + unescape::unescape_unicode(s, unescape::Mode::Str, &mut |range, ch| { if ch.is_ok() { res.push_str(&s[range]); } diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index aa25f82ae1d8d..bf1feb9a7eb07 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -379,14 +379,14 @@ fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str { let mut error_message = ""; match mode { Mode::CStr => { - rustc_lexer::unescape::unescape_c_string(text, mode, &mut |_, res| { + rustc_lexer::unescape::unescape_mixed(text, mode, &mut |_, res| { if let Err(e) = res { error_message = error_to_diagnostic_message(e, mode); } }); } Mode::ByteStr | Mode::Str => { - rustc_lexer::unescape::unescape_literal(text, mode, &mut |_, res| { + rustc_lexer::unescape::unescape_unicode(text, mode, &mut |_, res| { if let Err(e) = res { error_message = error_to_diagnostic_message(e, mode); } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs index 2f75e9677ec89..7cd1f1550b988 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs @@ -6,7 +6,7 @@ use std::{ }; use rustc_lexer::unescape::{ - unescape_byte, unescape_c_string, unescape_char, unescape_literal, MixedUnit, Mode, + unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode, }; use crate::{ @@ -193,7 +193,7 @@ pub trait IsString: AstToken { let text = &self.text()[text_range_no_quotes - start]; let offset = text_range_no_quotes.start() - start; - unescape_literal(text, Self::MODE, &mut |range, unescaped_char| { + unescape_unicode(text, Self::MODE, &mut |range, unescaped_char| { let text_range = TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()); cb(text_range + offset, unescaped_char); @@ -226,7 +226,7 @@ impl ast::String { let mut buf = String::new(); let mut prev_end = 0; let mut has_error = false; - unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match ( + unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match ( unescaped_char, buf.capacity() == 0, ) { @@ -270,7 +270,7 @@ impl ast::ByteString { let mut buf: Vec = Vec::new(); let mut prev_end = 0; let mut has_error = false; - unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match ( + unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match ( unescaped_char, buf.capacity() == 0, ) { @@ -311,7 +311,7 @@ impl IsString for ast::CString { let text = &self.text()[text_range_no_quotes - start]; let offset = text_range_no_quotes.start() - start; - unescape_c_string(text, Self::MODE, &mut |range, unescaped_char| { + unescape_mixed(text, Self::MODE, &mut |range, unescaped_char| { let text_range = TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()); // XXX: This method should only be used for highlighting ranges. The unescaped @@ -340,7 +340,7 @@ impl ast::CString { MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()), MixedUnit::HighByte(b) => buf.push(b), }; - unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match ( + unescape_mixed(text, Self::MODE, &mut |char_range, unescaped| match ( unescaped, buf.capacity() == 0, ) { diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index fadcbaef14330..5c5b26f525f66 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{self, unescape_c_string, unescape_literal, Mode}; +use rustc_lexer::unescape::{self, unescape_mixed, unescape_unicode, Mode}; use crate::{ algo, @@ -140,7 +140,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::String(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 1, '"') { - unescape_literal(without_quotes, Mode::Str, &mut |range, char| { + unescape_unicode(without_quotes, Mode::Str, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -151,7 +151,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::ByteString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { + unescape_unicode(without_quotes, Mode::ByteStr, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -162,7 +162,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::CString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_c_string(without_quotes, Mode::CStr, &mut |range, char| { + unescape_mixed(without_quotes, Mode::CStr, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -172,7 +172,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { } ast::LiteralKind::Char(_) => { if let Some(without_quotes) = unquote(text, 1, '\'') { - unescape_literal(without_quotes, Mode::Char, &mut |range, char| { + unescape_unicode(without_quotes, Mode::Char, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -181,7 +181,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { } ast::LiteralKind::Byte(_) => { if let Some(without_quotes) = unquote(text, 2, '\'') { - unescape_literal(without_quotes, Mode::Byte, &mut |range, char| { + unescape_unicode(without_quotes, Mode::Byte, &mut |range, char| { if let Err(err) = char { push_err(2, range.start, err); } From 56514076ac93e1417c8b4d15e3ce21da0dc6353f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 23 Jan 2024 12:27:56 +1100 Subject: [PATCH 203/676] Rework `CStrUnit`. - Rename it as `MixedUnit`, because it will soon be used in more than just C string literals. - Change the `Byte` variant to `HighByte` and use it only for `\x80`..`\xff` cases. This fixes the old inexactness where ASCII chars could be encoded with either `Byte` or `Char`. - Add useful comments. - Remove `is_ascii`, in favour of `u8::is_ascii`. --- crates/syntax/src/ast/token_ext.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index b39006e2ff265..2f75e9677ec89 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs @@ -6,7 +6,7 @@ use std::{ }; use rustc_lexer::unescape::{ - unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode, + unescape_byte, unescape_c_string, unescape_char, unescape_literal, MixedUnit, Mode, }; use crate::{ @@ -336,10 +336,9 @@ impl ast::CString { let mut buf = Vec::new(); let mut prev_end = 0; let mut has_error = false; - let mut char_buf = [0u8; 4]; - let mut extend_unit = |buf: &mut Vec, unit: CStrUnit| match unit { - CStrUnit::Byte(b) => buf.push(b), - CStrUnit::Char(c) => buf.extend(c.encode_utf8(&mut char_buf).as_bytes()), + let extend_unit = |buf: &mut Vec, unit: MixedUnit| match unit { + MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()), + MixedUnit::HighByte(b) => buf.push(b), }; unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match ( unescaped, From 6be2e5623cb7ae63ca1796759150c0cbc845bbcd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 24 Jan 2024 16:00:10 +1100 Subject: [PATCH 204/676] Use `unescape_unicode` for raw C string literals. They can't contain `\x` escapes, which means they can't contain high bytes, which means we can used `unescape_unicode` instead of `unescape_mixed` to unescape them. This avoids unnecessary used of `MixedUnit`. --- compiler/rustc_lexer/src/unescape.rs | 33 ++++++++++++--------------- compiler/rustc_parse/src/lexer/mod.rs | 2 +- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 4da6d35727cb5..03d178eb266a4 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -97,7 +97,13 @@ where } Str | ByteStr => unescape_non_raw_common(src, mode, callback), RawStr | RawByteStr => check_raw_common(src, mode, callback), - CStr | RawCStr => unreachable!(), + RawCStr => check_raw_common(src, mode, &mut |r, mut result| { + if let Ok('\0') = result { + result = Err(EscapeError::NulInCStr); + } + callback(r, result) + }), + CStr => unreachable!(), } } @@ -141,24 +147,13 @@ where F: FnMut(Range, Result), { match mode { - CStr => { - unescape_non_raw_common(src, mode, &mut |r, mut result| { - if let Ok(MixedUnit::Char('\0')) = result { - result = Err(EscapeError::NulInCStr); - } - callback(r, result) - }); - } - RawCStr => { - check_raw_common(src, mode, &mut |r, mut result| { - if let Ok('\0') = result { - result = Err(EscapeError::NulInCStr); - } - // High bytes aren't possible in raw strings. - callback(r, result.map(MixedUnit::Char)) - }); - } - Char | Byte | Str | RawStr | ByteStr | RawByteStr => unreachable!(), + CStr => unescape_non_raw_common(src, mode, &mut |r, mut result| { + if let Ok(MixedUnit::Char('\0')) = result { + result = Err(EscapeError::NulInCStr); + } + callback(r, result) + }), + Char | Byte | Str | RawStr | ByteStr | RawByteStr | RawCStr => unreachable!(), } } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index a491d1969bd5c..20ec4a300c1f8 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -472,7 +472,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { if let Some(n_hashes) = n_hashes { let n = u32::from(n_hashes); let kind = token::CStrRaw(n_hashes); - self.cook_mixed(kind, Mode::RawCStr, start, end, 3 + n, 1 + n) // cr##" "## + self.cook_unicode(kind, Mode::RawCStr, start, end, 3 + n, 1 + n) // cr##" "## } else { self.report_raw_str_error(start, 2); } From 858f4aca6c42a814f5fd6aa85e5eead827ee3a8b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 24 Jan 2024 15:24:58 +1100 Subject: [PATCH 205/676] Rename the unescaping functions. `unescape_literal` becomes `unescape_unicode`, and `unescape_c_string` becomes `unescape_mixed`. Because rfc3349 will mean that C string literals will no longer be the only mixed utf8 literals. --- crates/parser/src/lexed_str.rs | 4 ++-- crates/syntax/src/ast/token_ext.rs | 12 ++++++------ crates/syntax/src/validation.rs | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index aa25f82ae1d8d..bf1feb9a7eb07 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -379,14 +379,14 @@ fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str { let mut error_message = ""; match mode { Mode::CStr => { - rustc_lexer::unescape::unescape_c_string(text, mode, &mut |_, res| { + rustc_lexer::unescape::unescape_mixed(text, mode, &mut |_, res| { if let Err(e) = res { error_message = error_to_diagnostic_message(e, mode); } }); } Mode::ByteStr | Mode::Str => { - rustc_lexer::unescape::unescape_literal(text, mode, &mut |_, res| { + rustc_lexer::unescape::unescape_unicode(text, mode, &mut |_, res| { if let Err(e) = res { error_message = error_to_diagnostic_message(e, mode); } diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index 2f75e9677ec89..7cd1f1550b988 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs @@ -6,7 +6,7 @@ use std::{ }; use rustc_lexer::unescape::{ - unescape_byte, unescape_c_string, unescape_char, unescape_literal, MixedUnit, Mode, + unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode, }; use crate::{ @@ -193,7 +193,7 @@ pub trait IsString: AstToken { let text = &self.text()[text_range_no_quotes - start]; let offset = text_range_no_quotes.start() - start; - unescape_literal(text, Self::MODE, &mut |range, unescaped_char| { + unescape_unicode(text, Self::MODE, &mut |range, unescaped_char| { let text_range = TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()); cb(text_range + offset, unescaped_char); @@ -226,7 +226,7 @@ impl ast::String { let mut buf = String::new(); let mut prev_end = 0; let mut has_error = false; - unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match ( + unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match ( unescaped_char, buf.capacity() == 0, ) { @@ -270,7 +270,7 @@ impl ast::ByteString { let mut buf: Vec = Vec::new(); let mut prev_end = 0; let mut has_error = false; - unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match ( + unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match ( unescaped_char, buf.capacity() == 0, ) { @@ -311,7 +311,7 @@ impl IsString for ast::CString { let text = &self.text()[text_range_no_quotes - start]; let offset = text_range_no_quotes.start() - start; - unescape_c_string(text, Self::MODE, &mut |range, unescaped_char| { + unescape_mixed(text, Self::MODE, &mut |range, unescaped_char| { let text_range = TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()); // XXX: This method should only be used for highlighting ranges. The unescaped @@ -340,7 +340,7 @@ impl ast::CString { MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()), MixedUnit::HighByte(b) => buf.push(b), }; - unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match ( + unescape_mixed(text, Self::MODE, &mut |char_range, unescaped| match ( unescaped, buf.capacity() == 0, ) { diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index fadcbaef14330..5c5b26f525f66 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{self, unescape_c_string, unescape_literal, Mode}; +use rustc_lexer::unescape::{self, unescape_mixed, unescape_unicode, Mode}; use crate::{ algo, @@ -140,7 +140,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::String(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 1, '"') { - unescape_literal(without_quotes, Mode::Str, &mut |range, char| { + unescape_unicode(without_quotes, Mode::Str, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -151,7 +151,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::ByteString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { + unescape_unicode(without_quotes, Mode::ByteStr, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -162,7 +162,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::CString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_c_string(without_quotes, Mode::CStr, &mut |range, char| { + unescape_mixed(without_quotes, Mode::CStr, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -172,7 +172,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { } ast::LiteralKind::Char(_) => { if let Some(without_quotes) = unquote(text, 1, '\'') { - unescape_literal(without_quotes, Mode::Char, &mut |range, char| { + unescape_unicode(without_quotes, Mode::Char, &mut |range, char| { if let Err(err) = char { push_err(1, range.start, err); } @@ -181,7 +181,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { } ast::LiteralKind::Byte(_) => { if let Some(without_quotes) = unquote(text, 2, '\'') { - unescape_literal(without_quotes, Mode::Byte, &mut |range, char| { + unescape_unicode(without_quotes, Mode::Byte, &mut |range, char| { if let Err(err) = char { push_err(2, range.start, err); } From 3ea464f36aa8e5bcc0367891e4a77ce5d643ea3a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 21 Jan 2024 23:58:40 +0100 Subject: [PATCH 206/676] Add tests --- .../pattern/bindings-after-at/bind-by-copy.rs | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs index 2b349f0ed5f99..08e1d55f77335 100644 --- a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs +++ b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs @@ -1,13 +1,29 @@ -// run-pass +#![allow(unused)] // Test copy -struct A { a: i32, b: i32 } -struct B { a: i32, b: C } -struct D { a: i32, d: C } -#[derive(Copy,Clone)] -struct C { c: i32 } +struct A { + a: i32, + b: i32, +} +struct B { + a: i32, + b: C, +} +struct D { + a: i32, + d: C, +} +#[derive(Copy, Clone)] +struct C { + c: i32, +} +enum E { + E { a: i32, e: C }, + NotE, +} +#[rustfmt::skip] pub fn main() { match (A {a: 10, b: 20}) { x@A {a, b: 20} => { assert!(x.a == 10); assert!(a == 10); } @@ -23,6 +39,25 @@ pub fn main() { y.d.c = 30; assert_eq!(d.c, 20); + match (E::E { a: 10, e: C { c: 20 } }) { + x @ E::E{ a, e: C { c } } => { + //~^ ERROR use of moved value + assert!(matches!(x, E::E { a: 10, e: C { c: 20 } })); + assert!(a == 10); + assert!(c == 20); + } + _ => panic!(), + } + match (E::E { a: 10, e: C { c: 20 } }) { + mut x @ E::E{ a, e: C { mut c } } => { + //~^ ERROR use of moved value + x = E::NotE; + c += 30; + assert_eq!(c, 50); + } + _ => panic!(), + } + let some_b = Some(B { a: 10, b: C { c: 20 } }); // in irrefutable pattern From 96ff1a4538646b1a431914a285de43f744b3489d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 21 Jan 2024 21:52:58 +0100 Subject: [PATCH 207/676] Move `Or` test out of the loop --- .../src/build/matches/simplify.rs | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index a7f6f4873e383..c2e44a06321da 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -62,19 +62,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut existing_bindings = mem::take(&mut candidate.bindings); let mut new_bindings = Vec::new(); loop { - let match_pairs = mem::take(&mut candidate.match_pairs); - - if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = - &*match_pairs - { - existing_bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut existing_bindings); - candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats); - return true; - } - let mut changed = false; - for match_pair in match_pairs { + for match_pair in mem::take(&mut candidate.match_pairs) { match self.simplify_match_pair(match_pair, candidate) { Ok(()) => { changed = true; @@ -84,6 +73,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } } + // Avoid issue #69971: the binding order should be right to left if there are more // bindings after `@` to please the borrow checker // Ex @@ -102,18 +92,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate.bindings.clear(); if !changed { - existing_bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut existing_bindings); - // Move or-patterns to the end, because they can result in us - // creating additional candidates, so we want to test them as - // late as possible. - candidate - .match_pairs - .sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. })); - debug!(simplified = ?candidate, "simplify_candidate"); - return false; // if we were not able to simplify any, done. + // If we were not able to simplify anymore, done. + break; } } + + existing_bindings.extend_from_slice(&new_bindings); + mem::swap(&mut candidate.bindings, &mut existing_bindings); + + let did_expand_or = + if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = + &*candidate.match_pairs + { + candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats); + candidate.match_pairs.clear(); + true + } else { + false + }; + + // Move or-patterns to the end, because they can result in us + // creating additional candidates, so we want to test them as + // late as possible. + candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. })); + debug!(simplified = ?candidate, "simplify_candidate"); + + did_expand_or } /// Given `candidate` that has a single or-pattern for its match-pairs, From e9028789084b2d9ebb6fbadf54527daf78598510 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 21 Jan 2024 22:06:13 +0100 Subject: [PATCH 208/676] Clarify the binding dance --- .../src/build/matches/simplify.rs | 63 ++++++++++++------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index c2e44a06321da..8563c2d6dfbb7 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -38,16 +38,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: &mut Candidate<'pat, 'tcx>, ) -> bool { - // repeatedly simplify match pairs until fixed point is reached debug!("{candidate:#?}"); - - // existing_bindings and new_bindings exists to keep the semantics in order. + // `original_bindings` and `new_bindings` exist to keep the semantics in order. // Reversing the binding order for bindings after `@` changes the binding order in places - // it shouldn't be changed, for example `let (Some(a), Some(b)) = (x, y)` + // where it shouldn't be changed, for example `let (Some(a), Some(b)) = (x, y)`. // // To avoid this, the binding occurs in the following manner: - // * the bindings for one iteration of the following loop occurs in order (i.e. left to - // right) + // * the bindings for one iteration of the loop occurs in order (i.e. left to right) // * the bindings from the previous iteration of the loop is prepended to the bindings from // the current iteration (in the implementation this is done by mem::swap and extend) // * after all iterations, these new bindings are then appended to the bindings that were @@ -59,8 +56,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // binding in iter 2: [6, 7] // // final binding: [1, 2, 3, 6, 7, 4, 5] - let mut existing_bindings = mem::take(&mut candidate.bindings); + // + // This is because we treat refutable and irrefutable bindings differently. The binding + // order should be right-to-left if there are more _irrefutable_ bindings after `@` to + // please the borrow checker (#69971) + // Ex + // struct NonCopyStruct { + // copy_field: u32, + // } + // + // fn foo1(x: NonCopyStruct) { + // let y @ NonCopyStruct { copy_field: z } = x; + // // the above should turn into + // let z = x.copy_field; + // let y = x; + // } + // + // If however the bindings are refutable, i.e. under a test, then we keep the bindings + // left-to-right. + // Ex + // enum NonCopyEnum { + // Variant { copy_field: u32 }, + // None, + // } + // + // fn foo2(x: NonCopyEnum) { + // let y @ NonCopyEnum::Variant { copy_field: z } = x else { return }; + // // turns into + // let y = x; + // let z = (x as Variant).copy_field; + // // and raises an error + // } + let mut original_bindings = mem::take(&mut candidate.bindings); let mut new_bindings = Vec::new(); + // Repeatedly simplify match pairs until fixed point is reached loop { let mut changed = false; for match_pair in mem::take(&mut candidate.match_pairs) { @@ -74,19 +103,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - // Avoid issue #69971: the binding order should be right to left if there are more - // bindings after `@` to please the borrow checker - // Ex - // struct NonCopyStruct { - // copy_field: u32, - // } - // - // fn foo1(x: NonCopyStruct) { - // let y @ NonCopyStruct { copy_field: z } = x; - // // the above should turn into - // let z = x.copy_field; - // let y = x; - // } + // This does: new_bindings = candidate.bindings.take() ++ new_bindings candidate.bindings.extend_from_slice(&new_bindings); mem::swap(&mut candidate.bindings, &mut new_bindings); candidate.bindings.clear(); @@ -97,8 +114,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - existing_bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut existing_bindings); + // Restore original bindings and append the new ones. + // This does: candidate.bindings = original_bindings ++ new_bindings + mem::swap(&mut candidate.bindings, &mut original_bindings); + candidate.bindings.extend_from_slice(&new_bindings); let did_expand_or = if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = From 09d4613f20a6052bb8af7119b90cf64e288deda0 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 21 Jan 2024 23:36:33 +0100 Subject: [PATCH 209/676] Put new bindings first in refutable cases too --- .../src/build/matches/simplify.rs | 8 +- ...wise_branch.opt1.EarlyOtherwiseBranch.diff | 6 +- ...wise_branch.opt2.EarlyOtherwiseBranch.diff | 6 +- ...wise_branch.opt3.EarlyOtherwiseBranch.diff | 6 +- ...ement_tuple.opt1.EarlyOtherwiseBranch.diff | 12 +-- ...ch_68867.try_sum.EarlyOtherwiseBranch.diff | 48 ++++----- ...nch_noopt.noopt1.EarlyOtherwiseBranch.diff | 6 +- .../pattern/bindings-after-at/bind-by-copy.rs | 3 +- .../borrowck-move-and-move.rs | 4 +- .../borrowck-move-and-move.stderr | 30 +++--- .../borrowck-pat-by-move-and-ref-inverse.rs | 7 +- ...orrowck-pat-by-move-and-ref-inverse.stderr | 75 ++++--------- .../borrowck-pat-by-move-and-ref.rs | 3 + .../borrowck-pat-by-move-and-ref.stderr | 58 ++++++++-- .../borrowck-pat-ref-mut-and-ref.rs | 10 +- .../borrowck-pat-ref-mut-and-ref.stderr | 102 ++++++++++++------ .../borrowck-pat-ref-mut-twice.rs | 6 +- .../borrowck-pat-ref-mut-twice.stderr | 48 +++------ 18 files changed, 229 insertions(+), 209 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 8563c2d6dfbb7..9fab61803e887 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // let z = (x as Variant).copy_field; // // and raises an error // } - let mut original_bindings = mem::take(&mut candidate.bindings); + let original_bindings = mem::take(&mut candidate.bindings); let mut new_bindings = Vec::new(); // Repeatedly simplify match pairs until fixed point is reached loop { @@ -115,9 +115,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } // Restore original bindings and append the new ones. - // This does: candidate.bindings = original_bindings ++ new_bindings - mem::swap(&mut candidate.bindings, &mut original_bindings); - candidate.bindings.extend_from_slice(&new_bindings); + // This does: candidate.bindings = new_bindings ++ original_bindings + mem::swap(&mut candidate.bindings, &mut new_bindings); + candidate.bindings.extend_from_slice(&original_bindings); let did_expand_or = if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff index 7a374c5675ab9..8b427cff67780 100644 --- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff @@ -51,13 +51,13 @@ - } - - bb3: { - StorageLive(_8); - _8 = (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_9); _9 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_8); + _8 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_9); StorageDead(_8); + StorageDead(_9); - goto -> bb4; + goto -> bb3; } diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index 21f58a14a2b3f..b91a469225cd2 100644 --- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -58,13 +58,13 @@ - - bb4: { + bb2: { - StorageLive(_9); - _9 = (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_10); _10 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_9); + _9 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_10); StorageDead(_9); + StorageDead(_10); - goto -> bb6; + goto -> bb4; } diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff index e058c409cb596..cc16af721ca69 100644 --- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff @@ -51,13 +51,13 @@ - } - - bb3: { - StorageLive(_8); - _8 = (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_9); _9 = (((_3.1: std::option::Option) as Some).0: bool); + StorageLive(_8); + _8 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_9); StorageDead(_8); + StorageDead(_9); - goto -> bb4; + goto -> bb3; } diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff index f98d68e6ffce3..eb8926d27ee87 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff @@ -69,16 +69,16 @@ - bb4: { + bb3: { - StorageLive(_11); - _11 = (((_4.0: std::option::Option) as Some).0: u32); - StorageLive(_12); - _12 = (((_4.1: std::option::Option) as Some).0: u32); StorageLive(_13); _13 = (((_4.2: std::option::Option) as Some).0: u32); + StorageLive(_12); + _12 = (((_4.1: std::option::Option) as Some).0: u32); + StorageLive(_11); + _11 = (((_4.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_13); - StorageDead(_12); StorageDead(_11); + StorageDead(_12); + StorageDead(_13); - goto -> bb5; + goto -> bb4; } diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index 0c94794fa3ffe..79cf1c0e34ad5 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -116,12 +116,12 @@ } bb6: { - StorageLive(_12); - _39 = deref_copy (_4.0: &ViewportPercentageLength); - _12 = (((*_39) as Vw).0: f32); StorageLive(_13); - _40 = deref_copy (_4.1: &ViewportPercentageLength); - _13 = (((*_40) as Vw).0: f32); + _39 = deref_copy (_4.1: &ViewportPercentageLength); + _13 = (((*_39) as Vw).0: f32); + StorageLive(_12); + _40 = deref_copy (_4.0: &ViewportPercentageLength); + _12 = (((*_40) as Vw).0: f32); StorageLive(_14); StorageLive(_15); _15 = _12; @@ -132,18 +132,18 @@ StorageDead(_15); _3 = ViewportPercentageLength::Vw(move _14); StorageDead(_14); - StorageDead(_13); StorageDead(_12); + StorageDead(_13); goto -> bb10; } bb7: { - StorageLive(_17); - _41 = deref_copy (_4.0: &ViewportPercentageLength); - _17 = (((*_41) as Vh).0: f32); StorageLive(_18); - _42 = deref_copy (_4.1: &ViewportPercentageLength); - _18 = (((*_42) as Vh).0: f32); + _41 = deref_copy (_4.1: &ViewportPercentageLength); + _18 = (((*_41) as Vh).0: f32); + StorageLive(_17); + _42 = deref_copy (_4.0: &ViewportPercentageLength); + _17 = (((*_42) as Vh).0: f32); StorageLive(_19); StorageLive(_20); _20 = _17; @@ -154,18 +154,18 @@ StorageDead(_20); _3 = ViewportPercentageLength::Vh(move _19); StorageDead(_19); - StorageDead(_18); StorageDead(_17); + StorageDead(_18); goto -> bb10; } bb8: { - StorageLive(_22); - _43 = deref_copy (_4.0: &ViewportPercentageLength); - _22 = (((*_43) as Vmin).0: f32); StorageLive(_23); - _44 = deref_copy (_4.1: &ViewportPercentageLength); - _23 = (((*_44) as Vmin).0: f32); + _43 = deref_copy (_4.1: &ViewportPercentageLength); + _23 = (((*_43) as Vmin).0: f32); + StorageLive(_22); + _44 = deref_copy (_4.0: &ViewportPercentageLength); + _22 = (((*_44) as Vmin).0: f32); StorageLive(_24); StorageLive(_25); _25 = _22; @@ -176,18 +176,18 @@ StorageDead(_25); _3 = ViewportPercentageLength::Vmin(move _24); StorageDead(_24); - StorageDead(_23); StorageDead(_22); + StorageDead(_23); goto -> bb10; } bb9: { - StorageLive(_27); - _45 = deref_copy (_4.0: &ViewportPercentageLength); - _27 = (((*_45) as Vmax).0: f32); StorageLive(_28); - _46 = deref_copy (_4.1: &ViewportPercentageLength); - _28 = (((*_46) as Vmax).0: f32); + _45 = deref_copy (_4.1: &ViewportPercentageLength); + _28 = (((*_45) as Vmax).0: f32); + StorageLive(_27); + _46 = deref_copy (_4.0: &ViewportPercentageLength); + _27 = (((*_46) as Vmax).0: f32); StorageLive(_29); StorageLive(_30); _30 = _27; @@ -198,8 +198,8 @@ StorageDead(_30); _3 = ViewportPercentageLength::Vmax(move _29); StorageDead(_29); - StorageDead(_28); StorageDead(_27); + StorageDead(_28); goto -> bb10; } diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff index 09cdce718572e..af0337d0a7e71 100644 --- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff @@ -59,13 +59,13 @@ } bb5: { - StorageLive(_9); - _9 = (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_10); _10 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_9); + _9 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_10); StorageDead(_9); + StorageDead(_10); goto -> bb8; } diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs index 08e1d55f77335..253b2d8890100 100644 --- a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs +++ b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs @@ -1,3 +1,4 @@ +// run-pass #![allow(unused)] // Test copy @@ -41,7 +42,6 @@ pub fn main() { match (E::E { a: 10, e: C { c: 20 } }) { x @ E::E{ a, e: C { c } } => { - //~^ ERROR use of moved value assert!(matches!(x, E::E { a: 10, e: C { c: 20 } })); assert!(a == 10); assert!(c == 20); @@ -50,7 +50,6 @@ pub fn main() { } match (E::E { a: 10, e: C { c: 20 } }) { mut x @ E::E{ a, e: C { mut c } } => { - //~^ ERROR use of moved value x = E::NotE; c += 30; assert_eq!(c, 50); diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs index a61d682152407..bfb3c3b20d63c 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs @@ -15,8 +15,8 @@ fn main() { let a @ (b, c) = (u(), u()); //~ ERROR use of partially moved value match Ok(U) { - a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of moved value - //~^ ERROR use of moved value + a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of partially moved value + //~^ ERROR use of partially moved value } fn fun(a @ b: U) {} //~ ERROR use of moved value diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr index 324897151124c..ba0622090bb7d 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr @@ -40,35 +40,33 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref a @ (b, ref c) = (u(), u()); | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:18:16 +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:18:9 | -LL | match Ok(U) { - | ----- move occurs because value has type `Result`, which does not implement the `Copy` trait LL | a @ Ok(b) | a @ Err(b) => {} - | - ^ value used here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Ok(b) | a @ Err(b) => {} - | +++ +LL | ref a @ Ok(ref b) | a @ Err(b) => {} + | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:18:29 +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:18:21 | -LL | match Ok(U) { - | ----- move occurs because value has type `Result`, which does not implement the `Copy` trait LL | a @ Ok(b) | a @ Err(b) => {} - | - ^ value used here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | a @ Ok(b) | ref a @ Err(b) => {} - | +++ +LL | a @ Ok(b) | ref a @ Err(ref b) => {} + | +++ +++ error[E0382]: use of partially moved value --> $DIR/borrowck-move-and-move.rs:25:9 diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs index 06dc6e1c4da1f..ac57838f0298f 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs @@ -48,19 +48,17 @@ fn main() { //~^ ERROR borrow of moved value //~| ERROR borrow of moved value //~| ERROR borrow of moved value - //~| ERROR use of moved value + //~| ERROR use of partially moved value None => {} } match Some([U, U]) { mut a @ Some([ref b, ref mut c]) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } match Some(u()) { a @ Some(ref b) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } match Some((u(), u())) { @@ -68,13 +66,12 @@ fn main() { //~^ ERROR borrow of moved value //~| ERROR borrow of moved value //~| ERROR borrow of moved value - //~| ERROR use of moved value + //~| ERROR use of partially moved value None => {} } match Some([u(), u()]) { mut a @ Some([ref b, ref mut c]) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr index 1ed019f0a6927..fd7a51388bc10 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -215,7 +215,7 @@ LL | ref mut a @ Some([ref b, ref mut c]) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:9 | LL | a @ Some(ref b) => {} | ^ ----- value borrowed here after move @@ -229,7 +229,7 @@ LL | ref a @ Some(ref b) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:9 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^ --------- ----- value borrowed here after move @@ -244,7 +244,7 @@ LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:19 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^^^^^ --------- value borrowed here after move @@ -258,7 +258,7 @@ LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:38 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^ ----- value borrowed here after move @@ -272,7 +272,7 @@ LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:73:9 | LL | mut a @ Some([ref b, ref mut c]) => {} | ^^^^^ ----- --------- value borrowed here after move @@ -314,66 +314,33 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9 | -LL | match Some((U, U)) { - | ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | - value moved here ^ value used here after move - | -help: borrow this binding in the pattern to avoid moving the value - | -LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | +++ - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30 - | -LL | match Some([U, U]) { - | ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait -LL | mut a @ Some([ref b, ref mut c]) => {} - | ----- ^^^^^^^^^ value borrowed here after move - | | - | value moved here - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:18 - | -LL | match Some(u()) { - | --------- move occurs because value has type `Option`, which does not implement the `Copy` trait -LL | a @ Some(ref b) => {} - | - ^^^^^ value borrowed here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Some(ref b) => {} - | +++ +LL | ref a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:9 | -LL | match Some((u(), u())) { - | ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | - value moved here ^ value used here after move + | ^ - value partially moved here + | | + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | +++ - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30 - | -LL | match Some([u(), u()]) { - | ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait -LL | mut a @ Some([ref b, ref mut c]) => {} - | ----- ^^^^^^^^^ value borrowed here after move - | | - | value moved here +LL | ref a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11 @@ -457,6 +424,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {} | +++ -error: aborting due to 33 previous errors +error: aborting due to 30 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs index 0b0a7801049fe..095c871e8d205 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs @@ -58,11 +58,13 @@ fn main() { match Some([U, U]) { ref mut a @ Some([b, mut c]) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } match Some(u()) { ref a @ Some(b) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } match Some((u(), u())) { @@ -77,6 +79,7 @@ fn main() { match Some([u(), u()]) { ref mut a @ Some([b, mut c]) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr index c8c4d9b8fdb13..45ada8fd51606 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr @@ -125,7 +125,7 @@ LL | ref mut a @ Some([b, mut c]) => {} | value is mutably borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:65:9 | LL | ref a @ Some(b) => {} | ^^^^^ - value is moved into `b` here @@ -133,7 +133,7 @@ LL | ref a @ Some(b) => {} | value is borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:9 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- - value is moved into `e` here @@ -142,7 +142,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- value is moved into `c` here @@ -150,7 +150,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `b` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ - value is moved into `e` here @@ -158,7 +158,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `d` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:78:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9 | LL | ref mut a @ Some([b, mut c]) => {} | ^^^^^^^^^ - ----- value is moved into `c` here @@ -236,8 +236,36 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref mut a @ [b, ref mut c] = [u(), u()]; | +++ +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([b, ref mut c]) => {} + | +++ + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:65:9 + | +LL | ref a @ Some(b) => {} + | ^^^^^ - value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- value moved here @@ -251,7 +279,7 @@ LL | ref a @ Some((ref b @ ref mut c, ref d @ e)) => {} | +++ error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ - value moved here @@ -264,6 +292,20 @@ help: borrow this binding in the pattern to avoid moving the value LL | ref a @ Some((ref b @ mut c, ref d @ ref e)) => {} | +++ +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([b, ref mut c]) => {} + | +++ + error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11 | @@ -345,6 +387,6 @@ LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 36 previous errors +error: aborting due to 39 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs index 6bc0d346c111a..98f316dd74bdd 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -7,7 +7,7 @@ fn main() { match &mut Some(1) { ref mut z @ &mut Some(ref a) => { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable **z = None; println!("{}", *a); } @@ -76,8 +76,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *b = U; drop(a); } @@ -87,6 +87,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot assign to `*b`, as it is immutable for the pattern guard _ => {} } @@ -101,6 +103,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot move out of `b` in pattern guard //~| ERROR cannot move out of `b` in pattern guard _ => {} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index 0b432487615b2..9359244c6ebc1 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -138,7 +138,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -146,7 +146,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -154,7 +154,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^^^^^ --------- value is mutably borrowed by `b` here @@ -162,7 +162,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^^^^^ --------- value is mutably borrowed by `b` here @@ -170,7 +170,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -178,7 +178,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -186,7 +186,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -195,7 +195,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -204,7 +204,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -213,7 +213,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:138:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); | ^^^^^^^^^ ----- ----- value is borrowed by `c` here @@ -221,16 +221,16 @@ LL | let ref mut a @ (ref b, ref c) = (U, U); | | value is borrowed by `b` here | value is mutably borrowed by `a` here -error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31 +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9 | LL | ref mut z @ &mut Some(ref a) => { - | --------- ^^^^^ immutable borrow occurs here + | ^^^^^^^^^ ----- immutable borrow occurs here | | | mutable borrow occurs here ... -LL | **z = None; - | ---------- mutable borrow later used here +LL | println!("{}", *a); + | -- immutable borrow later used here error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9 @@ -254,27 +254,44 @@ LL | let ref a @ ref mut b = u(); LL | *b = u(); | -------- mutable borrow later used here -error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:20 +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - | ----- ^^^^^^^^^ mutable borrow occurs here + | ^^^^^ --------- mutable borrow occurs here | | | immutable borrow occurs here ... -LL | drop(a); - | - immutable borrow later used here +LL | *b = U; + | ------ mutable borrow later used here -error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:45 +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - | ----- ^^^^^^^^^ mutable borrow occurs here + | ^^^^^ --------- mutable borrow occurs here | | | immutable borrow occurs here ... -LL | drop(a); - | - immutable borrow later used here +LL | *b = U; + | ------ mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | ^^^^^ --------- mutable borrow occurs here ------ mutable borrow later used here + | | + | immutable borrow occurs here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | ^^^^^ --------- ------ mutable borrow later used here + | | | + | | mutable borrow occurs here + | immutable borrow occurs here error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:61 @@ -285,15 +302,32 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } = note: variables bound in patterns are immutable until the end of the pattern guard error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:61 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^^^ cannot assign | = note: variables bound in patterns are immutable until the end of the pattern guard +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^^^^^ --------- mutable borrow occurs here - mutable borrow later used here + | | + | immutable borrow occurs here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^^^^^ --------- - mutable borrow later used here + | | | + | | mutable borrow occurs here + | immutable borrow occurs here + error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait @@ -301,7 +335,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait @@ -310,7 +344,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait @@ -318,7 +352,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait @@ -327,7 +361,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -338,7 +372,7 @@ LL | *b = U; | ------ mutable borrow later used here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -349,7 +383,7 @@ LL | *b = U; | ------ mutable borrow later used here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -409,7 +443,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} | | value borrowed here after move | move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 47 previous errors +error: aborting due to 51 previous errors Some errors have detailed explanations: E0382, E0502, E0507, E0594. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs index 99739c7bce041..5f86a6a0ca919 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs @@ -82,6 +82,8 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time *b = U; } } @@ -89,8 +91,6 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time *a = Err(U); // FIXME: The binding name value used above makes for problematic diagnostics. @@ -101,8 +101,6 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time drop(a); } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index c634ea470c5d5..3446148d2b15b 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -163,7 +163,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ^^^^^^^^^ --------- value is mutably borrowed by `b` here @@ -171,7 +171,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:37 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ^^^^^^^^^ --------- value is mutably borrowed by `b` here @@ -217,48 +217,26 @@ LL | *b = U; | ------ first borrow later used here error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:24 - | -LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here - | | - | first mutable borrow occurs here -... -LL | *a = Err(U); - | ----------- first borrow later used here - -error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:53 - | -LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here - | | - | first mutable borrow occurs here -... -LL | *a = Err(U); - | ----------- first borrow later used here - -error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:101:24 + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here + | ^^^^^^^^^ --------- first mutable borrow occurs here | | - | first mutable borrow occurs here + | second mutable borrow occurs here ... -LL | drop(a); - | - first borrow later used here +LL | *b = U; + | ------ first borrow later used here error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:101:53 + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here + | ^^^^^^^^^ --------- first mutable borrow occurs here | | - | first mutable borrow occurs here + | second mutable borrow occurs here ... -LL | drop(a); - | - first borrow later used here +LL | *b = U; + | ------ first borrow later used here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11 @@ -313,7 +291,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} | | value borrowed here after move | move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 31 previous errors +error: aborting due to 29 previous errors Some errors have detailed explanations: E0382, E0499. For more information about an error, try `rustc --explain E0382`. From 0825ad3fb0488cbca375d6eb8d0af4dadbed5a91 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 21 Jan 2024 23:41:13 +0100 Subject: [PATCH 210/676] Clarify the new binding dance --- .../src/build/matches/simplify.rs | 64 ++++++------------- 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 9fab61803e887..3eb39d68d749b 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -39,28 +39,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate: &mut Candidate<'pat, 'tcx>, ) -> bool { debug!("{candidate:#?}"); - // `original_bindings` and `new_bindings` exist to keep the semantics in order. - // Reversing the binding order for bindings after `@` changes the binding order in places - // where it shouldn't be changed, for example `let (Some(a), Some(b)) = (x, y)`. + // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the + // bindings in `pat` before `x`. E.g. (#69971): // - // To avoid this, the binding occurs in the following manner: - // * the bindings for one iteration of the loop occurs in order (i.e. left to right) - // * the bindings from the previous iteration of the loop is prepended to the bindings from - // the current iteration (in the implementation this is done by mem::swap and extend) - // * after all iterations, these new bindings are then appended to the bindings that were - // preexisting (i.e. `candidate.binding` when the function was called). - // - // example: - // candidate.bindings = [1, 2, 3] - // binding in iter 1: [4, 5] - // binding in iter 2: [6, 7] - // - // final binding: [1, 2, 3, 6, 7, 4, 5] - // - // This is because we treat refutable and irrefutable bindings differently. The binding - // order should be right-to-left if there are more _irrefutable_ bindings after `@` to - // please the borrow checker (#69971) - // Ex // struct NonCopyStruct { // copy_field: u32, // } @@ -72,23 +53,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // let y = x; // } // - // If however the bindings are refutable, i.e. under a test, then we keep the bindings - // left-to-right. - // Ex - // enum NonCopyEnum { - // Variant { copy_field: u32 }, - // None, - // } + // We can't just reverse the binding order, because we must preserve pattern-order + // otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first, + // and bindings at the same depth stay in source order. // - // fn foo2(x: NonCopyEnum) { - // let y @ NonCopyEnum::Variant { copy_field: z } = x else { return }; - // // turns into - // let y = x; - // let z = (x as Variant).copy_field; - // // and raises an error - // } - let original_bindings = mem::take(&mut candidate.bindings); - let mut new_bindings = Vec::new(); + // To do this, every time around the loop we prepend the newly found bindings to the + // bindings we already had. + // + // example: + // candidate.bindings = [1, 2, 3] + // bindings in iter 1: [4, 5] + // bindings in iter 2: [6, 7] + // + // final bindings: [6, 7, 4, 5, 1, 2, 3] + let mut accumulated_bindings = mem::take(&mut candidate.bindings); // Repeatedly simplify match pairs until fixed point is reached loop { let mut changed = false; @@ -103,9 +81,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - // This does: new_bindings = candidate.bindings.take() ++ new_bindings - candidate.bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut new_bindings); + // This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings + candidate.bindings.extend_from_slice(&accumulated_bindings); + mem::swap(&mut candidate.bindings, &mut accumulated_bindings); candidate.bindings.clear(); if !changed { @@ -114,10 +92,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - // Restore original bindings and append the new ones. - // This does: candidate.bindings = new_bindings ++ original_bindings - mem::swap(&mut candidate.bindings, &mut new_bindings); - candidate.bindings.extend_from_slice(&original_bindings); + // Store computed bindings back in `candidate`. + mem::swap(&mut candidate.bindings, &mut accumulated_bindings); let did_expand_or = if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = From b1b6e0c41a09cdcfbd8a731e5489eb56df33d7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 25 Jan 2024 06:40:07 +0200 Subject: [PATCH 211/676] Reapply "Detect `NulInCStr` error earlier." This reverts commit 0ea056552a014a09b7aed40358f05c0676460af5. --- 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 f47ec49df1d9f..aa25f82ae1d8d 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -369,6 +369,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 6c6916c585f1f..69dffbf79f191 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 2aa746913bda5c52b3efeefb756e13c72618f793 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 25 Jan 2024 04:41:38 +0000 Subject: [PATCH 212/676] Don't fire OPAQUE_HIDDEN_INFERRED_BOUND on sized return of AFIT --- .../src/opaque_hidden_inferred_bound.rs | 13 ++++++++++++- .../returning-possibly-unsized-self.rs | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index f64509fe8bc67..bed5d3c80c046 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -4,7 +4,7 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{ self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable, }; -use rustc_span::Span; +use rustc_span::{symbol::kw, Span}; use rustc_trait_selection::traits; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -96,6 +96,17 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { continue; } + // HACK: `async fn() -> Self` in traits is "ok"... + // This is not really that great, but it's similar to why the `-> Self` + // return type is well-formed in traits even when `Self` isn't sized. + if let ty::Param(param_ty) = *proj_term.kind() + && param_ty.name == kw::SelfUpper + && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_)) + && opaque.in_trait + { + continue; + } + let proj_ty = Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args); // For every instance of the projection type in the bounds, diff --git a/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs b/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs new file mode 100644 index 0000000000000..72f02679d7712 --- /dev/null +++ b/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs @@ -0,0 +1,18 @@ +// check-pass +// edition:2021 + +#![deny(opaque_hidden_inferred_bound)] + +trait Repository /* : ?Sized */ { + async fn new() -> Self; +} + +struct MyRepository {} + +impl Repository for MyRepository { + async fn new() -> Self { + todo!() + } +} + +fn main() {} From b1b99cbcf90b5d1825e91f21d65445773b2cd7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 25 Jan 2024 06:42:48 +0200 Subject: [PATCH 213/676] Bump rustc_lexer and rustc_parse_format --- Cargo.lock | 10 +++++----- Cargo.toml | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bdb9feee5f12b..5578334e22cc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1476,9 +1476,9 @@ dependencies = [ [[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", @@ -1486,11 +1486,11 @@ 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 0.21.0", + "ra-ap-rustc_index 0.33.0", "ra-ap-rustc_lexer", ] diff --git a/Cargo.toml b/Cargo.toml index ed5b2eb9b2d58..478304c709bc3 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.21.0", default-features = false } -ra-ap-rustc_parse_format = { 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.21.0", default-features = false } ra-ap-rustc_abi = { version = "0.21.0", default-features = false } ra-ap-rustc_pattern_analysis = { version = "0.33.0", default-features = false } From ea94c10db01df312bb34f9b126f21129cb239e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 25 Jan 2024 06:44:13 +0200 Subject: [PATCH 214/676] Bump rustc_index and rustc_abi --- Cargo.lock | 39 ++++++++------------------------------- Cargo.toml | 4 ++-- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5578334e22cc0..7513abf17c8c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -592,7 +592,7 @@ dependencies = [ "profile", "project-model", "ra-ap-rustc_abi", - "ra-ap-rustc_index 0.21.0", + "ra-ap-rustc_index", "ra-ap-rustc_pattern_analysis", "rustc-hash", "scoped-tls", @@ -1419,26 +1419,15 @@ 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", - "ra-ap-rustc_index 0.21.0", + "bitflags 2.4.1", + "ra-ap-rustc_index", "tracing", ] -[[package]] -name = "ra-ap-rustc_index" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8352918d61aa4afab9f2ed7314cf638976b20949b3d61d2f468c975b0d251f24" -dependencies = [ - "arrayvec", - "ra-ap-rustc_index_macros 0.21.0", - "smallvec", -] - [[package]] name = "ra-ap-rustc_index" version = "0.33.0" @@ -1446,22 +1435,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5313d7f243b63ef9e58d94355b11aa8499f1328055f1f58adf0a5ea7d2faca" dependencies = [ "arrayvec", - "ra-ap-rustc_index_macros 0.33.0", + "ra-ap-rustc_index_macros", "smallvec", ] -[[package]] -name = "ra-ap-rustc_index_macros" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a9424018828155a3e3596515598f90e68427d8f35eff6df7f0856c73fc58a8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", - "synstructure", -] - [[package]] name = "ra-ap-rustc_index_macros" version = "0.33.0" @@ -1490,7 +1467,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab62fc925612374103b4f178da347b535b35d9eb1ff5ba42105c990b2e25a164" dependencies = [ - "ra-ap-rustc_index 0.33.0", + "ra-ap-rustc_index", "ra-ap-rustc_lexer", ] @@ -1501,7 +1478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c4085e0c771fd4b883930b599ef42966b855762bbe4052c17673b3253421a6d" dependencies = [ "derivative", - "ra-ap-rustc_index 0.33.0", + "ra-ap-rustc_index", "rustc-hash", "rustc_apfloat", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index 478304c709bc3..56db5a28c08a3 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.33.0", default-features = false } ra-ap-rustc_parse_format = { version = "0.33.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_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. From 4505f03fbfd8eeb326135d644afc83f159965b4f Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 25 Jan 2024 19:27:37 +0800 Subject: [PATCH 215/676] fix: filter out cfg disabled filed when lowering `RecordPat` --- crates/hir-def/src/body/lower.rs | 1 + 1 file changed, 1 insertion(+) 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(); From 1374bc8c936b1a8ae0d5e5cb4ac6db8373c34221 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 25 Jan 2024 19:30:04 +0800 Subject: [PATCH 216/676] test: ensure `no_such_field` diagnostic don't work for field with disabled cfg --- .../src/handlers/no_such_field.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) 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( From f68741b637c27ce2e7273207d3593759ba698a64 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Jan 2024 11:57:01 +0000 Subject: [PATCH 217/676] Stop checking `err_count` in macro_rules validity checking All errors are local anyway, so we can track them directly --- compiler/rustc_expand/src/mbe/macro_rules.rs | 39 ++++++++++++-------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 1a39708ed8ed8..83e0f870c8a25 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -485,7 +485,9 @@ pub fn compile_declarative_macro( ) .pop() .unwrap(); - valid &= check_lhs_nt_follows(sess, def, &tt); + // We don't handle errors here, the driver will abort + // after parsing/expansion. we can report every error in every macro this way. + valid &= check_lhs_nt_follows(sess, def, &tt).is_ok(); return tt; } sess.dcx().span_bug(def.span, "wrong-structured lhs") @@ -589,18 +591,19 @@ pub fn compile_declarative_macro( (mk_syn_ext(expander), rule_spans) } -fn check_lhs_nt_follows(sess: &Session, def: &ast::Item, lhs: &mbe::TokenTree) -> bool { +fn check_lhs_nt_follows( + sess: &Session, + def: &ast::Item, + lhs: &mbe::TokenTree, +) -> Result<(), ErrorGuaranteed> { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. if let mbe::TokenTree::Delimited(.., delimited) = lhs { check_matcher(sess, def, &delimited.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; - sess.dcx().span_err(lhs.span(), msg); - false + Err(sess.dcx().span_err(lhs.span(), msg)) } - // we don't abort on errors on rejection, the driver will do that for us - // after parsing/expansion. we can report every error in every macro this way. } fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool { @@ -675,12 +678,15 @@ fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> bool { false } -fn check_matcher(sess: &Session, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool { +fn check_matcher( + sess: &Session, + def: &ast::Item, + matcher: &[mbe::TokenTree], +) -> Result<(), ErrorGuaranteed> { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); - let err = sess.dcx().err_count(); - check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix); - err == sess.dcx().err_count() + check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix)?; + Ok(()) } fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool { @@ -1020,11 +1026,13 @@ fn check_matcher_core<'tt>( first_sets: &FirstSets<'tt>, matcher: &'tt [mbe::TokenTree], follow: &TokenSet<'tt>, -) -> TokenSet<'tt> { +) -> Result, ErrorGuaranteed> { use mbe::TokenTree; let mut last = TokenSet::empty(); + let mut errored = Ok(()); + // 2. For each token and suffix [T, SUFFIX] in M: // ensure that T can be followed by SUFFIX, and if SUFFIX may be empty, // then ensure T can also be followed by any element of FOLLOW. @@ -1068,7 +1076,7 @@ fn check_matcher_core<'tt>( token::CloseDelim(d.delim), span.close, )); - check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix); + check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix)?; // don't track non NT tokens last.replace_with_irrelevant(); @@ -1100,7 +1108,7 @@ fn check_matcher_core<'tt>( // At this point, `suffix_first` is built, and // `my_suffix` is some TokenSet that we can use // for checking the interior of `seq_rep`. - let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix); + let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix)?; if next.maybe_empty { last.add_all(&next); } else { @@ -1206,14 +1214,15 @@ fn check_matcher_core<'tt>( )); } } - err.emit(); + errored = Err(err.emit()); } } } } } } - last + errored?; + Ok(last) } fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool { From f6f0e04e9b9583fd3ba5a381d33894ebaa01d83f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Jan 2024 12:06:01 +0000 Subject: [PATCH 218/676] Remove an unused error count check --- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 13 ------------- .../clippy/clippy_lints/src/transmute/utils.rs | 18 +----------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 18f547be2a71c..b4c500206573e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -45,14 +45,6 @@ pub struct FnCtxt<'a, 'tcx> { /// eventually). pub(super) param_env: ty::ParamEnv<'tcx>, - /// Number of errors that had been reported when we started - /// checking this function. On exit, if we find that *more* errors - /// have been reported, we will skip regionck and other work that - /// expects the types within the function to be consistent. - // FIXME(matthewjasper) This should not exist, and it's not correct - // if type checking is run in parallel. - err_count_on_creation: usize, - /// If `Some`, this stores coercion information for returned /// expressions. If `None`, this is in a context where return is /// inappropriate, such as a const expression. @@ -126,7 +118,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { FnCtxt { body_id, param_env, - err_count_on_creation: inh.tcx.dcx().err_count(), ret_coercion: None, ret_coercion_span: Cell::new(None), coroutine_types: None, @@ -195,10 +186,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }), } } - - pub fn errors_reported_since_creation(&self) -> bool { - self.dcx().err_count() > self.err_count_on_creation - } } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 1cf6cf8548a64..7a7bb9f9c94c3 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -37,12 +37,6 @@ pub(super) fn check_cast<'tcx>( let inherited = Inherited::new(cx.tcx, local_def_id); let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_id); - // If we already have errors, we can't be sure we can pointer cast. - assert!( - !fn_ctxt.errors_reported_since_creation(), - "Newly created FnCtxt contained errors" - ); - if let Ok(check) = cast::CastCheck::new( &fn_ctxt, e, @@ -53,17 +47,7 @@ pub(super) fn check_cast<'tcx>( DUMMY_SP, hir::Constness::NotConst, ) { - let res = check.do_check(&fn_ctxt); - - // do_check's documentation says that it might return Ok and create - // errors in the fcx instead of returning Err in some cases. Those cases - // should be filtered out before getting here. - assert!( - !fn_ctxt.errors_reported_since_creation(), - "`fn_ctxt` contained errors after cast check!" - ); - - res.ok() + check.do_check(&fn_ctxt).ok() } else { None } From 15dbdabdb55adaf7542a42ec605aba7a4a299801 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 25 Jan 2024 13:25:29 +0300 Subject: [PATCH 219/676] privacy: Refactor top-level visiting in `NamePrivacyVisitor` --- compiler/rustc_privacy/src/lib.rs | 59 +++++++++---------------------- 1 file changed, 16 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ae10695fae453..31d3ce1712939 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -24,7 +24,6 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, PatKind}; -use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgs; @@ -36,9 +35,9 @@ use rustc_span::hygiene::Transparency; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; +use std::fmt; use std::marker::PhantomData; use std::ops::ControlFlow; -use std::{fmt, mem}; use errors::{ FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface, @@ -935,7 +934,6 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { struct NamePrivacyVisitor<'tcx> { tcx: TyCtxt<'tcx>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, - current_item: LocalDefId, } impl<'tcx> NamePrivacyVisitor<'tcx> { @@ -951,6 +949,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { // Checks that a field in a struct constructor (expression or pattern) is accessible. fn check_field( &mut self, + hir_id: hir::HirId, // ID of the field use use_ctxt: Span, // syntax context of the field name at the use site span: Span, // span of the field pattern, e.g., `x: 0` def: ty::AdtDef<'tcx>, // definition of the struct or enum @@ -963,7 +962,6 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { // definition of the field let ident = Ident::new(kw::Empty, use_ctxt); - let hir_id = self.tcx.local_def_id_to_hir_id(self.current_item); let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1; if !field.vis.is_accessible_from(def_id, self.tcx) { self.tcx.dcx().emit_err(FieldIsPrivate { @@ -982,33 +980,13 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { } impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { - type NestedFilter = nested_filter::All; - - /// We want to visit items in the context of their containing - /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { - // Don't visit nested modules, since we run a separate visitor walk - // for each module in `effective_visibilities` - } - - fn visit_nested_body(&mut self, body: hir::BodyId) { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { let old_maybe_typeck_results = - self.maybe_typeck_results.replace(self.tcx.typeck_body(body)); - let body = self.tcx.hir().body(body); - self.visit_body(body); + self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id)); + self.visit_body(self.tcx.hir().body(body_id)); self.maybe_typeck_results = old_maybe_typeck_results; } - fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id); - intravisit::walk_item(self, item); - self.current_item = orig_current_item; - } - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind { let res = self.typeck_results().qpath_res(qpath, expr.hir_id); @@ -1022,17 +1000,17 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { let field = fields .iter() .find(|f| self.typeck_results().field_index(f.hir_id) == vf_index); - let (use_ctxt, span) = match field { - Some(field) => (field.ident.span, field.span), - None => (base.span, base.span), + let (hir_id, use_ctxt, span) = match field { + Some(field) => (field.hir_id, field.ident.span, field.span), + None => (base.hir_id, base.span, base.span), }; - self.check_field(use_ctxt, span, adt, variant_field, true); + self.check_field(hir_id, use_ctxt, span, adt, variant_field, true); } } else { for field in fields { - let use_ctxt = field.ident.span; + let (hir_id, use_ctxt, span) = (field.hir_id, field.ident.span, field.span); let index = self.typeck_results().field_index(field.hir_id); - self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); + self.check_field(hir_id, use_ctxt, span, adt, &variant.fields[index], false); } } } @@ -1046,9 +1024,9 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { let adt = self.typeck_results().pat_ty(pat).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); for field in fields { - let use_ctxt = field.ident.span; + let (hir_id, use_ctxt, span) = (field.hir_id, field.ident.span, field.span); let index = self.typeck_results().field_index(field.hir_id); - self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); + self.check_field(hir_id, use_ctxt, span, adt, &variant.fields[index], false); } } @@ -1743,17 +1721,12 @@ pub fn provide(providers: &mut Providers) { fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { // Check privacy of names not checked in previous compilation stages. - let mut visitor = NamePrivacyVisitor { - tcx, - maybe_typeck_results: None, - current_item: module_def_id.to_local_def_id(), - }; - let (module, span, hir_id) = tcx.hir().get_module(module_def_id); - - intravisit::walk_mod(&mut visitor, module, hir_id); + let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None }; + tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor); // Check privacy of explicitly written types and traits as well as // inferred types of expressions and patterns. + let span = tcx.def_span(module_def_id); let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span }; tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor); } From 646c8fc2c1e9b4c8b67a21d8b40c820bd2aef7a7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Jan 2024 14:37:07 +0000 Subject: [PATCH 220/676] Statically ensure an error is reported in report_arg_errors --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 6a77450f075bf..405ba3928420e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|vars| self.resolve_vars_if_possible(vars)), ); - self.report_arg_errors( + self.set_tainted_by_errors(self.report_arg_errors( compatibility_diagonal, formal_and_expected_inputs, provided_args, @@ -433,7 +433,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_def_id, call_span, call_expr, - ); + )); } } @@ -447,7 +447,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_def_id: Option, call_span: Span, call_expr: &'tcx hir::Expr<'tcx>, - ) { + ) -> ErrorGuaranteed { // Next, let's construct the error let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind { hir::ExprKind::Call( @@ -486,10 +486,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let tcx = self.tcx; - // FIXME: taint after emitting errors and pass through an `ErrorGuaranteed` - self.set_tainted_by_errors( - tcx.dcx().span_delayed_bug(call_span, "no errors reported for args"), - ); // Get the argument span in the context of the call span so that // suggestions and labels are (more) correct when an arg is a @@ -696,8 +692,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(mismatch_idx), is_method, ); - err.emit(); - return; + return err.emit(); } } } @@ -721,11 +716,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if cfg!(debug_assertions) { span_bug!(error_span, "expected errors from argument matrix"); } else { - tcx.dcx().emit_err(errors::ArgMismatchIndeterminate { span: error_span }); + return tcx.dcx().emit_err(errors::ArgMismatchIndeterminate { span: error_span }); } - return; } + let mut reported = None; errors.retain(|error| { let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error @@ -736,16 +731,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty); if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) { - self.err_ctxt().report_and_explain_type_error(trace, *e).emit(); + reported = Some(self.err_ctxt().report_and_explain_type_error(trace, *e).emit()); return false; } true }); // We're done if we found errors, but we already emitted them. - if errors.is_empty() { - return; + if let Some(reported) = reported { + assert!(errors.is_empty()); + return reported; } + assert!(!errors.is_empty()); // Okay, now that we've emitted the special errors separately, we // are only left missing/extra/swapped and mismatched arguments, both @@ -802,8 +799,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(expected_idx.as_usize()), is_method, ); - err.emit(); - return; + return err.emit(); } let mut err = if formal_and_expected_inputs.len() == provided_args.len() { @@ -1251,7 +1247,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - err.emit(); + err.emit() } fn suggest_ptr_null_mut( From c2c6e333356f53338e6eecd710faf663217a0074 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Thu, 25 Jan 2024 06:59:51 -0800 Subject: [PATCH 221/676] Update primitive_docs.rs --- library/core/src/primitive_docs.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 939342c4d9760..fca2d3979ab47 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1403,6 +1403,10 @@ mod prim_usize {} /// If `t` points at address `a`, being "dereferenceable" for N bytes means that the memory range /// `[a, a + N)` is all contained within a single [allocated object]. /// +/// Note that the precise validity invariants for reference types are a work in progress. In the +/// future, new guarantees may be added. However, the guarantees documented in this section will +/// never be removed. +/// /// [allocated object]: ptr#allocated-object #[stable(feature = "rust1", since = "1.0.0")] mod prim_ref {} From abf45ae0b21d460a3bfd374e39034105b6cab08e Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Wed, 24 Jan 2024 16:03:44 +0100 Subject: [PATCH 222/676] core: add `From` implementations Introduce `From` implementations for all unsigned numeric types and `char`. This matches the API of `char` type. Issue: https://github.com/rust-lang/rust/issues/110998 --- library/core/src/ascii/ascii_char.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index cc872a5343d6a..5f758af162477 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -537,6 +537,22 @@ impl AsciiChar { } } +macro_rules! into_int_impl { + ($($ty:ty)*) => { + $( + #[unstable(feature = "ascii_char", issue = "110998")] + impl From for $ty { + #[inline] + fn from(chr: AsciiChar) -> $ty { + chr as u8 as $ty + } + } + )* + } +} + +into_int_impl!(u8 u16 u32 u64 u128 char); + impl [AsciiChar] { /// Views this slice of ASCII characters as a UTF-8 `str`. #[unstable(feature = "ascii_char", issue = "110998")] From c4208fad3ce9d851fe5d54ba030b07a5aa3e0a89 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 25 Jan 2024 16:32:44 +0100 Subject: [PATCH 223/676] bless --- tests/ui/traits/issue-77982.stderr | 1 + tests/ui/try-trait/bad-interconversion.stderr | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr index 592cfd970c64a..b130b7620fc0d 100644 --- a/tests/ui/traits/issue-77982.stderr +++ b/tests/ui/traits/issue-77982.stderr @@ -44,6 +44,7 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect( | type must be known at this point | = note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate: + - impl From for u32; - impl From for u32; - impl From for u32; - impl From for u32; diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index 97fbbdbf8f8a8..4d046635d6442 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -12,6 +12,7 @@ LL | Ok(Err(123_i32)?) = help: the following other types implement trait `From`: > > + > = note: required for `Result` to implement `FromResidual>` error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` From 2b60e56e1f2ead042ce74b857bda05060963b604 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Jan 2024 16:23:53 +0000 Subject: [PATCH 224/676] Statically ensure report_selection_error actually reports an error --- .../error_reporting/type_err_ctxt_ext.rs | 224 +++++++++--------- tests/ui/treat-err-as-bug/eagerly-emit.rs | 1 - tests/ui/treat-err-as-bug/eagerly-emit.stderr | 12 +- 3 files changed, 120 insertions(+), 117 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 149dcffe333de..ee2adc5a29ada 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 @@ -99,7 +99,7 @@ pub trait TypeErrCtxtExt<'tcx> { obligation: PredicateObligation<'tcx>, root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, - ); + ) -> ErrorGuaranteed; fn emit_specialized_closure_kind_error( &self, @@ -208,10 +208,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + let mut reported = None; + for from_expansion in [false, true] { for (error, suppressed) in iter::zip(&errors, &is_suppressed) { if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion { - self.report_fulfillment_error(error); + reported = Some(self.report_fulfillment_error(error)); // We want to ignore desugarings here: spans are equivalent even // if one is the result of a desugaring and the other is not. let mut span = error.obligation.cause.span; @@ -228,7 +230,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - self.dcx().delayed_bug("expected fulfillment errors") + // It could be that we don't report an error because we have seen an `ErrorReported` from another source. + // We should probably be able to fix most of these, but some are delayed bugs that get a proper error + // after this function. + reported.unwrap_or_else(|| self.dcx().delayed_bug("failed to report fulfillment errors")) } /// Reports that an overflow has occurred and halts compilation. We @@ -374,7 +379,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { mut obligation: PredicateObligation<'tcx>, root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, - ) { + ) -> ErrorGuaranteed { let tcx = self.tcx; if tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() @@ -384,10 +389,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } let mut span = obligation.cause.span; - // FIXME: statically guarantee this by tainting after the diagnostic is emitted - self.set_tainted_by_errors( - tcx.dcx().span_delayed_bug(span, "`report_selection_error` did not emit an error"), - ); let mut err = match *error { SelectionError::Unimplemented => { @@ -412,21 +413,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { kind: _, } = *obligation.cause.code() { - self.report_extra_impl_obligation( + return self.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, &format!("`{}`", obligation.predicate), ) - .emit(); - return; + .emit() } // Report a const-param specific error if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives() { - self.report_const_param_not_wf(ty, &obligation).emit(); - return; + return self.report_const_param_not_wf(ty, &obligation).emit(); } let bound_predicate = obligation.predicate.kind(); @@ -436,22 +435,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let trait_predicate = self.resolve_vars_if_possible(trait_predicate); let trait_ref = trait_predicate.to_poly_trait_ref(); - if let Some(_guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) { - return; + if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) { + return guar; } // FIXME(effects) let predicate_is_const = false; - if self.dcx().has_errors().is_some() + if let Some(guar) = self.dcx().has_errors() && trait_predicate.references_error() { - return; + return guar; } if self.fn_arg_obligation(&obligation) { // Silence redundant errors on binding acccess that are already // reported on the binding definition (#56607). - return; + return self.dcx().span_delayed_bug(obligation.cause.span, "error already reported"); } let mut file = None; let (post_message, pre_message, type_def) = self @@ -515,7 +514,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_ref, span, ) { - GetSafeTransmuteErrorAndReason::Silent => return, + GetSafeTransmuteErrorAndReason::Silent => return self.dcx().span_delayed_bug(span, "silent safe transmute error"), GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation, @@ -576,8 +575,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { have_alt_message, ) { self.note_obligation_cause(&mut err, &obligation); - err.emit(); - return; + return err.emit(); } file_note.map(|note| err.note(note)); @@ -680,13 +678,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { - err.emit(); - return; + return err.emit(); } if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) { - err.emit(); - return; + return err.emit(); } if is_unsize { @@ -776,8 +772,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { Some(sym::Debug | sym::Display) ) { - err.emit(); - return; + return err.emit(); } err @@ -912,8 +907,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { found_trait_ref, expected_trait_ref, ) { - Some(err) => err, - None => return, + Ok(err) => err, + Err(guar) => return guar, } } @@ -934,15 +929,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => { match self.report_not_const_evaluatable_error(&obligation, span) { - Some(err) => err, - None => return, + Ok(err) => err, + Err(guar) => return guar, } } // Already reported in the query. - SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) | + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) | // Already reported. - Overflow(OverflowError::Error(_)) => return, + Overflow(OverflowError::Error(guar)) => return guar, Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); @@ -951,7 +946,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); - err.emit(); + err.emit() } fn emit_specialized_closure_kind_error( @@ -1323,13 +1318,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> { // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>); + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed; fn report_projection_error( &self, obligation: &PredicateObligation<'tcx>, error: &MismatchedProjectionTypes<'tcx>, - ); + ) -> ErrorGuaranteed; fn maybe_detailed_projection_msg( &self, @@ -1395,7 +1390,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, ) -> PredicateObligation<'tcx>; - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>); + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed; fn predicate_can_apply( &self, @@ -1512,13 +1507,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> { span: Span, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Option>; + ) -> Result, ErrorGuaranteed>; fn report_not_const_evaluatable_error( &self, obligation: &PredicateObligation<'tcx>, span: Span, - ) -> Option>; + ) -> Result, ErrorGuaranteed>; } impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { @@ -1564,7 +1559,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed { if self.tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() == DumpSolverProofTree::OnError { @@ -1572,31 +1567,29 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } match error.code { - FulfillmentErrorCode::SelectionError(ref selection_error) => { - self.report_selection_error( + FulfillmentErrorCode::SelectionError(ref selection_error) => self + .report_selection_error( error.obligation.clone(), &error.root_obligation, selection_error, - ); - } + ), FulfillmentErrorCode::ProjectionError(ref e) => { - self.report_projection_error(&error.obligation, e); + self.report_projection_error(&error.obligation, e) } FulfillmentErrorCode::Ambiguity { overflow: false } => { - self.maybe_report_ambiguity(&error.obligation); + self.maybe_report_ambiguity(&error.obligation) } FulfillmentErrorCode::Ambiguity { overflow: true } => { - self.report_overflow_no_abort(error.obligation.clone()); + self.report_overflow_no_abort(error.obligation.clone()) } - FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => { - self.report_mismatched_types( + FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => self + .report_mismatched_types( &error.obligation.cause, expected_found.expected, expected_found.found, *err, ) - .emit(); - } + .emit(), FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => { let mut diag = self.report_mismatched_consts( &error.obligation.cause, @@ -1620,11 +1613,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &mut Default::default(), ); } - diag.emit(); - } - FulfillmentErrorCode::Cycle(ref cycle) => { - self.report_overflow_obligation_cycle(cycle); + diag.emit() } + FulfillmentErrorCode::Cycle(ref cycle) => self.report_overflow_obligation_cycle(cycle), } } @@ -1633,11 +1624,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, error: &MismatchedProjectionTypes<'tcx>, - ) { + ) -> ErrorGuaranteed { let predicate = self.resolve_vars_if_possible(obligation.predicate); - if predicate.references_error() { - return; + if let Err(e) = predicate.error_reported() { + return e; } self.probe(|_| { @@ -1802,8 +1793,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { false, ); self.note_obligation_cause(&mut diag, obligation); - diag.emit(); - }); + diag.emit() + }) } fn maybe_detailed_projection_msg( @@ -2341,7 +2332,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed { // Unable to successfully determine, probably means // insufficient type information, but could mean // ambiguous impls. The latter *ought* to be a @@ -2361,8 +2352,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let trait_ref = bound_predicate.rebind(data.trait_ref); debug!(?trait_ref); - if predicate.references_error() { - return; + if let Err(e) = predicate.error_reported() { + return e; } // This is kind of a hack: it frequently happens that some earlier @@ -2381,17 +2372,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // check upstream for type errors and don't add the obligations to // begin with in those cases. if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { - if let None = self.tainted_by_errors() { - let err = self.emit_inference_failure_err( - obligation.cause.body_id, - span, - trait_ref.self_ty().skip_binder().into(), - ErrorCode::E0282, - false, - ); - err.stash(span, StashKey::MaybeForgetReturn); + match self.tainted_by_errors() { + None => { + let err = self.emit_inference_failure_err( + obligation.cause.body_id, + span, + trait_ref.self_ty().skip_binder().into(), + ErrorCode::E0282, + false, + ); + err.stash(span, StashKey::MaybeForgetReturn); + return self.dcx().delayed_bug("stashed error never reported"); + } + Some(e) => return e, } - return; } // Typically, this ambiguity should only happen if @@ -2450,19 +2444,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer { - if self.tainted_by_errors().is_some() && subst.is_none() { + if let Some(e) = self.tainted_by_errors() + && subst.is_none() + { // If `subst.is_none()`, then this is probably two param-env // candidates or impl candidates that are equal modulo lifetimes. // Therefore, if we've already emitted an error, just skip this // one, since it's not particularly actionable. err.cancel(); - return; + return e; } self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate); } else { - if self.tainted_by_errors().is_some() { + if let Some(e) = self.tainted_by_errors() { err.cancel(); - return; + return e; } err.note(format!("cannot satisfy `{predicate}`")); let impl_candidates = self @@ -2605,11 +2601,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { // Same hacky approach as above to avoid deluging user // with error messages. - if arg.references_error() - || self.dcx().has_errors().is_some() - || self.tainted_by_errors().is_some() - { - return; + + if let Err(e) = arg.error_reported() { + return e; + } + 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( @@ -2622,12 +2622,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::Subtype(data) => { - if data.references_error() - || self.dcx().has_errors().is_some() - || self.tainted_by_errors().is_some() - { + if let Err(e) = data.error_reported() { + return e; + } + 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; + return e; } let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated @@ -2641,8 +2644,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { - if predicate.references_error() || self.tainted_by_errors().is_some() { - return; + if let Err(e) = predicate.error_reported() { + return e; + } + if let Some(e) = self.tainted_by_errors() { + return e; } let subst = data .projection_ty @@ -2673,8 +2679,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => { - if predicate.references_error() || self.tainted_by_errors().is_some() { - return; + if let Err(e) = predicate.error_reported() { + return e; + } + if let Some(e) = self.tainted_by_errors() { + return e; } let subst = data.walk().find(|g| g.is_non_region_infer()); if let Some(subst) = subst { @@ -2699,8 +2708,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } _ => { - if self.dcx().has_errors().is_some() || self.tainted_by_errors().is_some() { - return; + 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(), @@ -2713,7 +2726,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } }; self.note_obligation_cause(&mut err, obligation); - err.emit(); + err.emit() } fn annotate_source_of_ambiguity( @@ -3433,16 +3446,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { span: Span, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Option> { + ) -> Result, ErrorGuaranteed> { let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref); let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref); - if expected_trait_ref.self_ty().references_error() { - return None; - } + expected_trait_ref.self_ty().error_reported()?; let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else { - return None; + return Err(self.dcx().delayed_bug("bound vars outside binder")); }; let found_did = match *found_trait_ty.kind() { @@ -3456,7 +3467,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) { // We check closures twice, with obligations flowing in different directions, // but we want to complain about them only once. - return None; + return Err(self.dcx().span_delayed_bug(span, "already_reported")); } let mut not_tupled = false; @@ -3485,7 +3496,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // This shouldn't be common unless manually implementing one of the // traits manually, but don't make it more confusing when it does // happen. - Some( + Ok( if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().coroutine_trait() && not_tupled { @@ -3534,9 +3545,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, span: Span, - ) -> Option> { + ) -> Result, ErrorGuaranteed> { if !self.tcx.features().generic_const_exprs { - self.dcx() + let guar = self + .dcx() .struct_span_err(span, "constant expression depends on a generic parameter") // FIXME(const_generics): we should suggest to the user how they can resolve this // issue. However, this is currently not actually possible @@ -3546,7 +3558,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // be reachable. .with_note("this may fail depending on what value the parameter takes") .emit(); - return None; + return Err(guar); } match obligation.predicate.kind().skip_binder() { @@ -3561,13 +3573,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { )), _ => err.help("consider adding a `where` bound using this expression"), }; - Some(err) + Ok(err) } ty::ConstKind::Expr(_) => { let err = self .dcx() .struct_span_err(span, format!("unconstrained generic constant `{ct}`")); - Some(err) + Ok(err) } _ => { bug!("const evaluatable failed for non-unevaluated const `{ct:?}`"); diff --git a/tests/ui/treat-err-as-bug/eagerly-emit.rs b/tests/ui/treat-err-as-bug/eagerly-emit.rs index 5f32f5a1d94b7..ede190575d529 100644 --- a/tests/ui/treat-err-as-bug/eagerly-emit.rs +++ b/tests/ui/treat-err-as-bug/eagerly-emit.rs @@ -6,6 +6,5 @@ fn main() {} fn f() -> impl Foo { //~^ ERROR the trait bound `i32: Foo` is not satisfied - //~| ERROR `report_selection_error` did not emit an error 1i32 } diff --git a/tests/ui/treat-err-as-bug/eagerly-emit.stderr b/tests/ui/treat-err-as-bug/eagerly-emit.stderr index 3d25741d52de8..4ae596435aa7f 100644 --- a/tests/ui/treat-err-as-bug/eagerly-emit.stderr +++ b/tests/ui/treat-err-as-bug/eagerly-emit.stderr @@ -1,9 +1,3 @@ -error: `report_selection_error` did not emit an error - --> $DIR/eagerly-emit.rs:7:11 - | -LL | fn f() -> impl Foo { - | ^^^^^^^^ - error: trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging error[E0277]: the trait bound `i32: Foo` is not satisfied @@ -11,7 +5,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied | LL | fn f() -> impl Foo { | ^^^^^^^^ the trait `Foo` is not implemented for `i32` -... +LL | LL | 1i32 | ---- return type was inferred to be `i32` here | @@ -21,8 +15,6 @@ help: this trait has no implementations, consider adding one LL | trait Foo {} | ^^^^^^^^^ -error: expected fulfillment errors - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. From 3042da02485920f5a9d4c4149cc9e2a7d7ef69d0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Jan 2024 17:12:09 +0000 Subject: [PATCH 225/676] Remove has_errors check in builtin macro parsing --- compiler/rustc_builtin_macros/src/format.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index eb331ef585301..b66f7111ff006 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -139,7 +139,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult< _ => { let expr = p.parse_expr()?; if !args.named_args().is_empty() { - ecx.dcx().emit_err(errors::PositionalAfterNamed { + return Err(ecx.dcx().create_err(errors::PositionalAfterNamed { span: expr.span, args: args .named_args() @@ -147,7 +147,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult< .filter_map(|a| a.kind.ident().map(|ident| (a, ident))) .map(|(arg, n)| n.span.to(arg.expr.span)) .collect(), - }); + })); } args.add(FormatArgument { kind: FormatArgumentKind::Normal, expr }); } @@ -313,6 +313,8 @@ fn make_format_args( } use ArgRef::*; + let mut unnamed_arg_after_named_arg = false; + let mut lookup_arg = |arg: ArgRef<'_>, span: Option, used_as: PositionUsedAs, @@ -352,6 +354,7 @@ fn make_format_args( // For the moment capturing variables from format strings expanded from macros is // disabled (see RFC #2795) ecx.dcx().emit_err(errors::FormatNoArgNamed { span, name }); + unnamed_arg_after_named_arg = true; DummyResult::raw_expr(span, true) }; Ok(args.add(FormatArgument { kind: FormatArgumentKind::Captured(ident), expr })) @@ -510,7 +513,8 @@ fn make_format_args( }) .collect::>(); - if !unused.is_empty() { + let has_unused = !unused.is_empty(); + if has_unused { // If there's a lot of unused arguments, // let's check if this format arguments looks like another syntax (printf / shell). let detect_foreign_fmt = unused.len() > args.explicit_args().len() / 2; @@ -529,7 +533,7 @@ fn make_format_args( // Only check for unused named argument names if there are no other errors to avoid causing // too much noise in output errors, such as when a named argument is entirely unused. - if invalid_refs.is_empty() && ecx.dcx().has_errors().is_none() { + if invalid_refs.is_empty() && !has_unused && !unnamed_arg_after_named_arg { for &(index, span, used_as) in &numeric_refences_to_named_arg { let (position_sp_to_replace, position_sp_for_msg) = match used_as { Placeholder(pspan) => (span, pspan), From 054e1e3aada8ab0dd08af1f2f8e7ee16139d96e7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Jan 2024 17:19:12 +0000 Subject: [PATCH 226/676] Track ErrorGuaranteed instead of conjuring it from thin air --- compiler/rustc_infer/src/infer/mod.rs | 3 +- .../error_reporting/type_err_ctxt_ext.rs | 31 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 1eab8575fc0c4..0a39fe007fd22 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -278,7 +278,8 @@ pub struct InferCtxt<'tcx> { /// The set of predicates on which errors have been reported, to /// avoid reporting the same error twice. - pub reported_trait_errors: RefCell>>>, + pub reported_trait_errors: + RefCell>, ErrorGuaranteed)>>, pub reported_signature_mismatch: RefCell)>>, 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 ee2adc5a29ada..48084a41f251f 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 @@ -107,7 +107,10 @@ pub trait TypeErrCtxtExt<'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, ) -> Option; - fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool; + fn fn_arg_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> Result<(), ErrorGuaranteed>; fn try_conversion_context( &self, @@ -142,6 +145,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ( span, predicates + .0 .iter() .map(|&predicate| ErrorDescriptor { predicate, index: None }) .collect(), @@ -213,7 +217,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { for from_expansion in [false, true] { for (error, suppressed) in iter::zip(&errors, &is_suppressed) { if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion { - reported = Some(self.report_fulfillment_error(error)); + let guar = self.report_fulfillment_error(error); + reported = Some(guar); // We want to ignore desugarings here: spans are equivalent even // if one is the result of a desugaring and the other is not. let mut span = error.obligation.cause.span; @@ -224,7 +229,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.reported_trait_errors .borrow_mut() .entry(span) - .or_default() + .or_insert_with(|| (vec![], guar)) + .0 .push(error.obligation.predicate); } } @@ -447,10 +453,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { return guar; } - if self.fn_arg_obligation(&obligation) { - // Silence redundant errors on binding acccess that are already - // reported on the binding definition (#56607). - return self.dcx().span_delayed_bug(obligation.cause.span, "error already reported"); + // Silence redundant errors on binding acccess that are already + // reported on the binding definition (#56607). + if let Err(guar) = self.fn_arg_obligation(&obligation) { + return guar; } let mut file = None; let (post_message, pre_message, type_def) = self @@ -981,7 +987,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool { + fn fn_arg_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> Result<(), ErrorGuaranteed> { if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() && let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id) @@ -991,12 +1000,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) = arg.kind && let Some(Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) - && let Some(preds) = self.reported_trait_errors.borrow().get(&pat.span) + && let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span) && preds.contains(&obligation.predicate) { - return true; + return Err(*guar); } - false + Ok(()) } /// When the `E` of the resulting `Result` in an expression `foo().bar().baz()?`, From c08c756e1232d26dd6b23c4fe3e01d50298fabc8 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 25 Jan 2024 18:39:50 +0100 Subject: [PATCH 227/676] Bump nightly version -> 2024-01-25 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 2589d46e7da07..d2d56e59ee3fb 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-01-11" +channel = "nightly-2024-01-25" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] From d7a0182157de02a49f1a3e219bcd8c29b388be41 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 25 Jan 2024 19:17:52 +0100 Subject: [PATCH 228/676] Update Cargo.lock --- Cargo.lock | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09eb0d98efc90..6c97786d8aeb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -587,11 +587,11 @@ dependencies = [ name = "clippy_dev" version = "0.0.1" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick 1.0.2", "clap", "indoc", "itertools", - "opener 0.5.2", + "opener", "shell-escape", "walkdir", ] @@ -601,7 +601,7 @@ name = "clippy_lints" version = "0.1.77" dependencies = [ "arrayvec", - "cargo_metadata 0.15.4", + "cargo_metadata 0.18.0", "clippy_config", "clippy_utils", "declare_clippy_lint", @@ -2342,7 +2342,7 @@ dependencies = [ "log", "memchr", "once_cell", - "opener 0.6.1", + "opener", "pathdiff", "pulldown-cmark", "regex", @@ -2617,16 +2617,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "opener" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" -dependencies = [ - "bstr", - "winapi", -] - [[package]] name = "opener" version = "0.6.1" From 8f05e7ce558ff83c1a42ebe8e85b2f65a84413d2 Mon Sep 17 00:00:00 2001 From: Ar4ys Date: Thu, 25 Jan 2024 20:15:46 +0100 Subject: [PATCH 229/676] Replaced adjusted_display_range with it's new version in mismatched_arg_count --- .../src/handlers/mismatched_arg_count.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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()?; ( From f9259d1b73f01c4c690dfd7429bb3ce25a34874f Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 9 May 2023 01:04:32 -0400 Subject: [PATCH 230/676] Boost intersperse(_with) performance I did some benchmark digging into the `intersperse` and `intersperse_with` code as part of the https://internals.rust-lang.org/t/add-iterate-with-separators-iterator-function/18781/13 discussion, and as a result I optimized them a bit, without relying on the peekable iterator. --- library/core/src/iter/adapters/intersperse.rs | 126 ++++++++++-------- 1 file changed, 74 insertions(+), 52 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index d8bbd424cf258..654e30777719c 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -1,4 +1,5 @@ -use super::Peekable; +use core::fmt; +use core::iter::{Fuse, FusedIterator}; /// An iterator adapter that places a separator between all elements. /// @@ -11,8 +12,16 @@ where I::Item: Clone, { separator: I::Item, - iter: Peekable, - needs_sep: bool, + next_item: Option, + iter: Fuse, +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl FusedIterator for Intersperse +where + I: FusedIterator, + I::Item: Clone, +{ } impl Intersperse @@ -20,7 +29,8 @@ where I::Item: Clone, { pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { - Self { iter: iter.peekable(), separator, needs_sep: false } + let mut iter = iter.fuse(); + Self { separator, next_item: iter.next(), iter } } } @@ -33,27 +43,31 @@ where type Item = I::Item; #[inline] - fn next(&mut self) -> Option { - if self.needs_sep && self.iter.peek().is_some() { - self.needs_sep = false; - Some(self.separator.clone()) + fn next(&mut self) -> Option { + if let Some(v) = self.next_item.take() { + Some(v) } else { - self.needs_sep = true; - self.iter.next() + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some(self.separator.clone()) + } else { + None + } } } + fn size_hint(&self) -> (usize, Option) { + intersperse_size_hint(&self.iter, self.next_item.is_some()) + } + fn fold(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { let separator = self.separator; - intersperse_fold(self.iter, init, f, move || separator.clone(), self.needs_sep) - } - - fn size_hint(&self) -> (usize, Option) { - intersperse_size_hint(&self.iter, self.needs_sep) + intersperse_fold(self.iter, init, f, move || separator.clone(), self.next_item) } } @@ -67,38 +81,46 @@ where I: Iterator, { separator: G, - iter: Peekable, - needs_sep: bool, + next_item: Option, + iter: Fuse, +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl FusedIterator for IntersperseWith +where + I: FusedIterator, + G: FnMut() -> I::Item, +{ } #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] -impl crate::fmt::Debug for IntersperseWith +impl fmt::Debug for IntersperseWith where - I: Iterator + crate::fmt::Debug, - I::Item: crate::fmt::Debug, - G: crate::fmt::Debug, + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, + G: fmt::Debug, { - fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("IntersperseWith") .field("separator", &self.separator) .field("iter", &self.iter) - .field("needs_sep", &self.needs_sep) + .field("next_item", &self.next_item) .finish() } } #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] -impl crate::clone::Clone for IntersperseWith +impl Clone for IntersperseWith where - I: Iterator + crate::clone::Clone, - I::Item: crate::clone::Clone, + I: Iterator + Clone, + I::Item: Clone, G: Clone, { fn clone(&self) -> Self { - IntersperseWith { + Self { separator: self.separator.clone(), iter: self.iter.clone(), - needs_sep: self.needs_sep.clone(), + next_item: self.next_item.clone(), } } } @@ -109,7 +131,8 @@ where G: FnMut() -> I::Item, { pub(in crate::iter) fn new(iter: I, separator: G) -> Self { - Self { iter: iter.peekable(), separator, needs_sep: false } + let mut iter = iter.fuse(); + Self { separator, next_item: iter.next(), iter } } } @@ -122,47 +145,50 @@ where type Item = I::Item; #[inline] - fn next(&mut self) -> Option { - if self.needs_sep && self.iter.peek().is_some() { - self.needs_sep = false; - Some((self.separator)()) + fn next(&mut self) -> Option { + if let Some(v) = self.next_item.take() { + Some(v) } else { - self.needs_sep = true; - self.iter.next() + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some((self.separator)()) + } else { + None + } } } + fn size_hint(&self) -> (usize, Option) { + intersperse_size_hint(&self.iter, self.next_item.is_some()) + } + fn fold(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - intersperse_fold(self.iter, init, f, self.separator, self.needs_sep) - } - - fn size_hint(&self) -> (usize, Option) { - intersperse_size_hint(&self.iter, self.needs_sep) + intersperse_fold(self.iter, init, f, self.separator, self.next_item) } } -fn intersperse_size_hint(iter: &I, needs_sep: bool) -> (usize, Option) +fn intersperse_size_hint(iter: &I, next_is_elem: bool) -> (usize, Option) where I: Iterator, { let (lo, hi) = iter.size_hint(); - let next_is_elem = !needs_sep; ( - lo.saturating_sub(next_is_elem as usize).saturating_add(lo), - hi.and_then(|hi| hi.saturating_sub(next_is_elem as usize).checked_add(hi)), + lo.saturating_add(next_is_elem as usize).saturating_add(lo), + hi.map(|hi| hi.saturating_add(next_is_elem as usize).saturating_add(hi)), ) } fn intersperse_fold( - mut iter: I, + iter: I, init: B, mut f: F, mut separator: G, - needs_sep: bool, + mut next_item: Option, ) -> B where I: Iterator, @@ -171,12 +197,8 @@ where { let mut accum = init; - if !needs_sep { - if let Some(x) = iter.next() { - accum = f(accum, x); - } else { - return accum; - } + if let Some(x) = next_item.take() { + accum = f(accum, x); } iter.fold(accum, |mut accum, x| { From b8d245e7490be49fedf0609bd9763adc1116b725 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 9 May 2023 18:31:56 -0400 Subject: [PATCH 231/676] Postpone .next() call until iteration --- library/core/src/iter/adapters/intersperse.rs | 78 ++++++++++++------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 654e30777719c..2ff24cd7792f9 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -11,6 +11,7 @@ pub struct Intersperse where I::Item: Clone, { + started: bool, separator: I::Item, next_item: Option, iter: Fuse, @@ -29,8 +30,7 @@ where I::Item: Clone, { pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { - let mut iter = iter.fuse(); - Self { separator, next_item: iter.next(), iter } + Self { started: false, separator, next_item: None, iter: iter.fuse() } } } @@ -44,21 +44,26 @@ where #[inline] fn next(&mut self) -> Option { - if let Some(v) = self.next_item.take() { - Some(v) - } else { - let next_item = self.iter.next(); - if next_item.is_some() { - self.next_item = next_item; - Some(self.separator.clone()) + if self.started { + if let Some(v) = self.next_item.take() { + Some(v) } else { - None + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some(self.separator.clone()) + } else { + None + } } + } else { + self.started = true; + self.iter.next() } } fn size_hint(&self) -> (usize, Option) { - intersperse_size_hint(&self.iter, self.next_item.is_some()) + intersperse_size_hint(&self.iter, self.started, self.next_item.is_some()) } fn fold(self, init: B, f: F) -> B @@ -67,7 +72,7 @@ where F: FnMut(B, Self::Item) -> B, { let separator = self.separator; - intersperse_fold(self.iter, init, f, move || separator.clone(), self.next_item) + intersperse_fold(self.iter, init, f, move || separator.clone(), self.started,self.next_item) } } @@ -80,6 +85,7 @@ pub struct IntersperseWith where I: Iterator, { + started: bool, separator: G, next_item: Option, iter: Fuse, @@ -102,6 +108,7 @@ where { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("IntersperseWith") + .field("started", &self.started) .field("separator", &self.separator) .field("iter", &self.iter) .field("next_item", &self.next_item) @@ -118,6 +125,7 @@ where { fn clone(&self) -> Self { Self { + started: self.started, separator: self.separator.clone(), iter: self.iter.clone(), next_item: self.next_item.clone(), @@ -131,8 +139,7 @@ where G: FnMut() -> I::Item, { pub(in crate::iter) fn new(iter: I, separator: G) -> Self { - let mut iter = iter.fuse(); - Self { separator, next_item: iter.next(), iter } + Self { started: false, separator, next_item: None, iter: iter.fuse() } } } @@ -146,21 +153,26 @@ where #[inline] fn next(&mut self) -> Option { - if let Some(v) = self.next_item.take() { - Some(v) - } else { - let next_item = self.iter.next(); - if next_item.is_some() { - self.next_item = next_item; - Some((self.separator)()) + if self.started { + if let Some(v) = self.next_item.take() { + Some(v) } else { - None + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some((self.separator)()) + } else { + None + } } + } else { + self.started = true; + self.iter.next() } } fn size_hint(&self) -> (usize, Option) { - intersperse_size_hint(&self.iter, self.next_item.is_some()) + intersperse_size_hint(&self.iter, self.started, self.next_item.is_some()) } fn fold(self, init: B, f: F) -> B @@ -168,26 +180,33 @@ where Self: Sized, F: FnMut(B, Self::Item) -> B, { - intersperse_fold(self.iter, init, f, self.separator, self.next_item) + intersperse_fold(self.iter, init, f, self.separator, self.started, self.next_item) } } -fn intersperse_size_hint(iter: &I, next_is_elem: bool) -> (usize, Option) +fn intersperse_size_hint(iter: &I, started: bool, next_is_some: bool) -> (usize, Option) where I: Iterator, { let (lo, hi) = iter.size_hint(); ( - lo.saturating_add(next_is_elem as usize).saturating_add(lo), - hi.map(|hi| hi.saturating_add(next_is_elem as usize).saturating_add(hi)), + lo.saturating_sub(!started as usize) + .saturating_add(next_is_some as usize) + .saturating_add(lo), + hi.map(|hi| { + hi.saturating_sub(!started as usize) + .saturating_add(next_is_some as usize) + .saturating_add(hi) + }), ) } fn intersperse_fold( - iter: I, + mut iter: I, init: B, mut f: F, mut separator: G, + started: bool, mut next_item: Option, ) -> B where @@ -197,7 +216,8 @@ where { let mut accum = init; - if let Some(x) = next_item.take() { + let first = if started { next_item.take() } else { iter.next() }; + if let Some(x) = first { accum = f(accum, x); } From f1dbc7b35ed70847237046a5a61af1ba88eae31d Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 9 May 2023 18:40:54 -0400 Subject: [PATCH 232/676] fmt --- library/core/src/iter/adapters/intersperse.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 2ff24cd7792f9..aab3743a51af2 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -72,7 +72,14 @@ where F: FnMut(B, Self::Item) -> B, { let separator = self.separator; - intersperse_fold(self.iter, init, f, move || separator.clone(), self.started,self.next_item) + intersperse_fold( + self.iter, + init, + f, + move || separator.clone(), + self.started, + self.next_item, + ) } } From 7d3b29399d03e552ff2b141275537a648cfd247e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 25 Jan 2024 21:16:03 +0000 Subject: [PATCH 233/676] Use sess.cfg_version instead of rustc_version_str() This makes it easier to patch cg_clif to be statically linked as part of rustc. --- src/debuginfo/mod.rs | 11 ++++------- src/driver/aot.rs | 18 +++++++++++++++--- src/lib.rs | 1 - 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index e6edc452cfb08..2d9c2ecdbc2be 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -13,17 +13,14 @@ use gimli::write::{ }; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian}; use indexmap::IndexSet; +use rustc_session::Session; pub(crate) use self::emit::{DebugReloc, DebugRelocName}; pub(crate) use self::unwind::UnwindContext; use crate::prelude::*; -pub(crate) fn producer() -> String { - format!( - "rustc version {} with cranelift {}", - rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), - cranelift_codegen::VERSION, - ) +pub(crate) fn producer(sess: &Session) -> String { + format!("rustc version {} with cranelift {}", sess.cfg_version, cranelift_codegen::VERSION) } pub(crate) struct DebugContext { @@ -67,7 +64,7 @@ impl DebugContext { let should_remap_filepaths = tcx.sess.should_prefer_remapped_for_codegen(); - let producer = producer(); + let producer = producer(tcx.sess); let comp_dir = tcx .sess .opts diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 6cfbb52e92180..757082a5fed1c 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -143,6 +143,7 @@ fn emit_cgu( debug: Option, unwind_context: UnwindContext, global_asm_object_file: Option, + producer: &str, ) -> Result { let mut product = module.finish(); @@ -152,8 +153,14 @@ fn emit_cgu( unwind_context.emit(&mut product); - let module_regular = - emit_module(output_filenames, prof, product.object, ModuleKind::Regular, name.clone())?; + let module_regular = emit_module( + output_filenames, + prof, + product.object, + ModuleKind::Regular, + name.clone(), + producer, + )?; Ok(ModuleCodegenResult { module_regular, @@ -174,6 +181,7 @@ fn emit_module( mut object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, name: String, + producer_str: &str, ) -> Result { if object.format() == cranelift_object::object::BinaryFormat::Elf { let comment_section = object.add_section( @@ -182,7 +190,7 @@ fn emit_module( cranelift_object::object::SectionKind::OtherString, ); let mut producer = vec![0]; - producer.extend(crate::debuginfo::producer().as_bytes()); + producer.extend(producer_str.as_bytes()); producer.push(0); object.set_section_data(comment_section, producer, 1); } @@ -321,6 +329,8 @@ fn module_codegen( (cgu_name, cx, module, codegened_functions) }); + let producer = crate::debuginfo::producer(tcx.sess); + OngoingModuleCodegen::Async(std::thread::spawn(move || { cx.profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| { cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler( @@ -348,6 +358,7 @@ fn module_codegen( cx.debug_context, cx.unwind_context, global_asm_object_file, + &producer, ) }); std::mem::drop(token); @@ -453,6 +464,7 @@ pub(crate) fn run_aot( product.object, ModuleKind::Allocator, "allocator_shim".to_owned(), + &crate::debuginfo::producer(tcx.sess), ) { Ok(allocator_module) => Some(allocator_module), Err(err) => tcx.dcx().fatal(err), diff --git a/src/lib.rs b/src/lib.rs index 635ff0ba7097e..416f87fcc87b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,6 @@ extern crate rustc_fs_util; extern crate rustc_hir; extern crate rustc_incremental; extern crate rustc_index; -extern crate rustc_interface; extern crate rustc_metadata; extern crate rustc_session; extern crate rustc_span; From 8cbff0b426b0f8821c6852545b8ed6aa74bfeffe Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 25 Jan 2024 20:33:06 -0500 Subject: [PATCH 234/676] Update library/core/src/iter/adapters/intersperse.rs Co-authored-by: Josh Stone --- library/core/src/iter/adapters/intersperse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index aab3743a51af2..f436fe02dca93 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -1,5 +1,5 @@ -use core::fmt; -use core::iter::{Fuse, FusedIterator}; +use crate::fmt; +use crate::iter::{Fuse, FusedIterator}; /// An iterator adapter that places a separator between all elements. /// From 77f31ef2b29e0ff16b9db8907327741c057bea8e Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 25 Jan 2024 20:56:52 -0500 Subject: [PATCH 235/676] use checked_add for upper bound --- library/core/src/iter/adapters/intersperse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index f436fe02dca93..c97a59b614f9d 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -200,10 +200,10 @@ where lo.saturating_sub(!started as usize) .saturating_add(next_is_some as usize) .saturating_add(lo), - hi.map(|hi| { + hi.and_then(|hi| { hi.saturating_sub(!started as usize) .saturating_add(next_is_some as usize) - .saturating_add(hi) + .checked_add(hi) }), ) } From 6e53e66bd3b700b873ba93b30fac7c065954d46f Mon Sep 17 00:00:00 2001 From: h1467792822 <1467792822@qq.com> Date: Tue, 5 Dec 2023 12:42:57 +0800 Subject: [PATCH 236/676] MCP #705: Provide the option `-Csymbol-mangling-version=hashed -Z unstable-options` to shorten symbol names by replacing them with a digest. Enrich test cases --- compiler/rustc_session/src/config.rs | 15 +++ compiler/rustc_session/src/options.rs | 6 +- compiler/rustc_symbol_mangling/src/hashed.rs | 43 ++++++++ compiler/rustc_symbol_mangling/src/lib.rs | 4 + compiler/rustc_symbol_mangling/src/v0.rs | 104 ++++++++++-------- .../run-make/symbol-mangling-hashed/Makefile | 48 ++++++++ .../symbol-mangling-hashed/a_dylib.rs | 4 + .../run-make/symbol-mangling-hashed/a_rlib.rs | 5 + .../run-make/symbol-mangling-hashed/b_bin.rs | 9 ++ .../symbol-mangling-hashed/b_dylib.rs | 9 ++ .../bad-value.bad.stderr | 2 +- .../bad-value.blank.stderr | 2 +- .../bad-value.no-value.stderr | 2 +- .../unstable.hashed.stderr | 2 + tests/ui/symbol-mangling-version/unstable.rs | 5 +- 15 files changed, 211 insertions(+), 49 deletions(-) create mode 100644 compiler/rustc_symbol_mangling/src/hashed.rs create mode 100644 tests/run-make/symbol-mangling-hashed/Makefile create mode 100644 tests/run-make/symbol-mangling-hashed/a_dylib.rs create mode 100644 tests/run-make/symbol-mangling-hashed/a_rlib.rs create mode 100644 tests/run-make/symbol-mangling-hashed/b_bin.rs create mode 100644 tests/run-make/symbol-mangling-hashed/b_dylib.rs create mode 100644 tests/ui/symbol-mangling-version/unstable.hashed.stderr diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index e751ff13a34ca..2ec1a726cef1f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -347,6 +347,7 @@ impl SwitchWithOptPath { pub enum SymbolManglingVersion { Legacy, V0, + Hashed, } #[derive(Clone, Copy, Debug, PartialEq, Hash)] @@ -2692,6 +2693,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M match cg.symbol_mangling_version { // Stable values: None | Some(SymbolManglingVersion::V0) => {} + // Unstable values: Some(SymbolManglingVersion::Legacy) => { if !unstable_opts.unstable_options { @@ -2700,6 +2702,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M ); } } + Some(SymbolManglingVersion::Hashed) => { + if !unstable_opts.unstable_options { + early_dcx.early_fatal( + "`-C symbol-mangling-version=hashed` requires `-Z unstable-options`", + ); + } + } } // Check for unstable values of `-C instrument-coverage`. @@ -2741,6 +2750,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M ); } Some(SymbolManglingVersion::V0) => {} + Some(SymbolManglingVersion::Hashed) => { + early_dcx.early_warn( + "-C instrument-coverage requires symbol mangling version `v0`, \ + but `-C symbol-mangling-version=hashed` was specified", + ); + } } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 486b6d4bf2e14..d8d201d5f244d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -407,7 +407,8 @@ mod desc { pub const parse_switch_with_opt_path: &str = "an optional path to the profiling data output directory"; pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`"; - pub const parse_symbol_mangling_version: &str = "either `legacy` or `v0` (RFC 2603)"; + pub const parse_symbol_mangling_version: &str = + "one of: `legacy`, `v0` (RFC 2603), or `hashed`"; pub const parse_src_file_hash: &str = "either `md5` or `sha1`"; pub const parse_relocation_model: &str = "one of supported relocation models (`rustc --print relocation-models`)"; @@ -1180,6 +1181,7 @@ mod parse { *slot = match v { Some("legacy") => Some(SymbolManglingVersion::Legacy), Some("v0") => Some(SymbolManglingVersion::V0), + Some("hashed") => Some(SymbolManglingVersion::Hashed), _ => return false, }; true @@ -1504,7 +1506,7 @@ options! { "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), symbol_mangling_version: Option = (None, parse_symbol_mangling_version, [TRACKED], - "which mangling version to use for symbol names ('legacy' (default) or 'v0')"), + "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], diff --git a/compiler/rustc_symbol_mangling/src/hashed.rs b/compiler/rustc_symbol_mangling/src/hashed.rs new file mode 100644 index 0000000000000..d4cd6161ac040 --- /dev/null +++ b/compiler/rustc_symbol_mangling/src/hashed.rs @@ -0,0 +1,43 @@ +use crate::v0; +use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; +use rustc_hir::def_id::CrateNum; +use rustc_middle::ty::{Instance, TyCtxt}; + +use std::fmt::Write; + +pub(super) fn mangle<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + instantiating_crate: Option, + full_mangling_name: impl FnOnce() -> String, +) -> String { + // The symbol of a generic function may be scattered in multiple downstream dylibs. + // If the symbol of a generic function still contains `crate name`, hash conflicts between the + // generic funcion and other symbols of the same `crate` cannot be detected in time during + // construction. This symbol conflict is left over until it occurs during run time. + // In this case, `instantiating-crate name` is used to replace `crate name` can completely + // eliminate the risk of the preceding potential hash conflict. + let crate_num = + if let Some(krate) = instantiating_crate { krate } else { instance.def_id().krate }; + + let mut symbol = "_RNxC".to_string(); + v0::push_ident(tcx.crate_name(crate_num).as_str(), &mut symbol); + + let hash = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + full_mangling_name().hash_stable(&mut hcx, &mut hasher); + hasher.finish::().as_u64() + }); + + push_hash64(hash, &mut symbol); + + symbol +} + +// The hash is encoded based on `base-62` and the final terminator `_` is removed because it does +// not help prevent hash collisions +fn push_hash64(hash: u64, output: &mut String) { + let hash = v0::encode_integer_62(hash); + let hash_len = hash.len(); + let _ = write!(output, "{hash_len}H{}", &hash[..hash_len - 1]); +} diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 8c035ba948b15..bf4ea0003abb4 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -111,6 +111,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_session::config::SymbolManglingVersion; +mod hashed; mod legacy; mod v0; @@ -265,6 +266,9 @@ fn compute_symbol_name<'tcx>( let symbol = match mangling_version { SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate), SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate), + SymbolManglingVersion::Hashed => hashed::mangle(tcx, instance, instantiating_crate, || { + v0::mangle(tcx, instance, instantiating_crate) + }), }; debug_assert!( diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index e89a640767f22..16ebda55a7a51 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -116,10 +116,7 @@ impl<'tcx> SymbolMangler<'tcx> { /// * `x > 0` is encoded as `x - 1` in base 62, followed by `"_"`, /// e.g. `1` becomes `"0_"`, `62` becomes `"Z_"`, etc. fn push_integer_62(&mut self, x: u64) { - if let Some(x) = x.checked_sub(1) { - base_n::push_str(x as u128, 62, &mut self.out); - } - self.push("_"); + push_integer_62(x, &mut self.out) } /// Push a `tag`-prefixed base 62 integer, when larger than `0`, that is: @@ -138,45 +135,7 @@ impl<'tcx> SymbolMangler<'tcx> { } fn push_ident(&mut self, ident: &str) { - let mut use_punycode = false; - for b in ident.bytes() { - match b { - b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => {} - 0x80..=0xff => use_punycode = true, - _ => bug!("symbol_names: bad byte {} in ident {:?}", b, ident), - } - } - - let punycode_string; - let ident = if use_punycode { - self.push("u"); - - // FIXME(eddyb) we should probably roll our own punycode implementation. - let mut punycode_bytes = match punycode::encode(ident) { - Ok(s) => s.into_bytes(), - Err(()) => bug!("symbol_names: punycode encoding failed for ident {:?}", ident), - }; - - // Replace `-` with `_`. - if let Some(c) = punycode_bytes.iter_mut().rfind(|&&mut c| c == b'-') { - *c = b'_'; - } - - // FIXME(eddyb) avoid rechecking UTF-8 validity. - punycode_string = String::from_utf8(punycode_bytes).unwrap(); - &punycode_string - } else { - ident - }; - - let _ = write!(self.out, "{}", ident.len()); - - // Write a separating `_` if necessary (leading digit or `_`). - if let Some('_' | '0'..='9') = ident.chars().next() { - self.push("_"); - } - - self.push(ident); + push_ident(ident, &mut self.out) } fn path_append_ns( @@ -836,3 +795,62 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { Ok(()) } } +/// Push a `_`-terminated base 62 integer, using the format +/// specified in the RFC as ``, that is: +/// * `x = 0` is encoded as just the `"_"` terminator +/// * `x > 0` is encoded as `x - 1` in base 62, followed by `"_"`, +/// e.g. `1` becomes `"0_"`, `62` becomes `"Z_"`, etc. +pub(crate) fn push_integer_62(x: u64, output: &mut String) { + if let Some(x) = x.checked_sub(1) { + base_n::push_str(x as u128, 62, output); + } + output.push('_'); +} + +pub(crate) fn encode_integer_62(x: u64) -> String { + let mut output = String::new(); + push_integer_62(x, &mut output); + output +} + +pub(crate) fn push_ident(ident: &str, output: &mut String) { + let mut use_punycode = false; + for b in ident.bytes() { + match b { + b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => {} + 0x80..=0xff => use_punycode = true, + _ => bug!("symbol_names: bad byte {} in ident {:?}", b, ident), + } + } + + let punycode_string; + let ident = if use_punycode { + output.push('u'); + + // FIXME(eddyb) we should probably roll our own punycode implementation. + let mut punycode_bytes = match punycode::encode(ident) { + Ok(s) => s.into_bytes(), + Err(()) => bug!("symbol_names: punycode encoding failed for ident {:?}", ident), + }; + + // Replace `-` with `_`. + if let Some(c) = punycode_bytes.iter_mut().rfind(|&&mut c| c == b'-') { + *c = b'_'; + } + + // FIXME(eddyb) avoid rechecking UTF-8 validity. + punycode_string = String::from_utf8(punycode_bytes).unwrap(); + &punycode_string + } else { + ident + }; + + let _ = write!(output, "{}", ident.len()); + + // Write a separating `_` if necessary (leading digit or `_`). + if let Some('_' | '0'..='9') = ident.chars().next() { + output.push('_'); + } + + output.push_str(ident); +} diff --git a/tests/run-make/symbol-mangling-hashed/Makefile b/tests/run-make/symbol-mangling-hashed/Makefile new file mode 100644 index 0000000000000..68894b2192aba --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/Makefile @@ -0,0 +1,48 @@ +include ../tools.mk + +# ignore-cross-compile +# only-linux +# only-x86_64 + +NM=nm -D +RLIB_NAME=liba_rlib.rlib +DYLIB_NAME=liba_dylib.so +SO_NAME=libb_dylib.so +BIN_NAME=b_bin + +ifeq ($(UNAME),Darwin) +NM=nm -gU +RLIB_NAME=liba_rlib.rlib +DYLIB_NAME=liba_dylib.dylib +SO_NAME=libb_dylib.dylib +BIN_NAME=b_bin +endif + +ifdef IS_WINDOWS +NM=nm -g +RLIB_NAME=liba_rlib.dll.a +DYLIB_NAME=liba_dylib.dll +SO_NAME=libb_dylib.dll +BIN_NAME=b_bin.exe +endif + +all: + $(RUSTC) -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=hashed -C metadata=foo a_dylib.rs + $(RUSTC) -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=hashed -C metadata=bar a_rlib.rs + $(RUSTC) -C prefer-dynamic -L $(TMPDIR) b_dylib.rs + $(RUSTC) -C prefer-dynamic -L $(TMPDIR) b_bin.rs + + # Check hashed symbol name + + [ "$$($(NM) $(TMPDIR)/$(DYLIB_NAME) | grep -c hello)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(DYLIB_NAME) | grep _RNxC7a_dylib | grep -c ' T ')" -eq "1" ] + + [ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep b_dylib | grep -c hello)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep _RNxC6a_rlib | grep -c ' T ')" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep _RNxC7a_dylib | grep -c ' U ')" -eq "1" ] + + [ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep _RNxC6a_rlib | grep -c ' U ')" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep _RNxC7a_dylib | grep -c ' U ')" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep b_dylib | grep hello | grep -c ' U ')" -eq "1" ] + + $(call RUN,$(BIN_NAME)) diff --git a/tests/run-make/symbol-mangling-hashed/a_dylib.rs b/tests/run-make/symbol-mangling-hashed/a_dylib.rs new file mode 100644 index 0000000000000..8aec8fd82a53f --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/a_dylib.rs @@ -0,0 +1,4 @@ +#![crate_type="dylib"] +pub fn hello() { + println!("hello dylib"); +} diff --git a/tests/run-make/symbol-mangling-hashed/a_rlib.rs b/tests/run-make/symbol-mangling-hashed/a_rlib.rs new file mode 100644 index 0000000000000..873c86c5d0b4c --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/a_rlib.rs @@ -0,0 +1,5 @@ +#![crate_type="rlib"] + +pub fn hello() { + println!("hello rlib"); +} diff --git a/tests/run-make/symbol-mangling-hashed/b_bin.rs b/tests/run-make/symbol-mangling-hashed/b_bin.rs new file mode 100644 index 0000000000000..bcc53c37e122a --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/b_bin.rs @@ -0,0 +1,9 @@ +extern crate a_rlib; +extern crate a_dylib; +extern crate b_dylib; + +fn main() { + a_rlib::hello(); + a_dylib::hello(); + b_dylib::hello(); +} diff --git a/tests/run-make/symbol-mangling-hashed/b_dylib.rs b/tests/run-make/symbol-mangling-hashed/b_dylib.rs new file mode 100644 index 0000000000000..c26a04b39ec32 --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/b_dylib.rs @@ -0,0 +1,9 @@ +#![crate_type="dylib"] + +extern crate a_rlib; +extern crate a_dylib; + +pub fn hello() { + a_rlib::hello(); + a_dylib::hello(); +} diff --git a/tests/ui/symbol-mangling-version/bad-value.bad.stderr b/tests/ui/symbol-mangling-version/bad-value.bad.stderr index c36c73c6069f1..a12e5e241c022 100644 --- a/tests/ui/symbol-mangling-version/bad-value.bad.stderr +++ b/tests/ui/symbol-mangling-version/bad-value.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad-value` for codegen option `symbol-mangling-version` - either `legacy` or `v0` (RFC 2603) was expected +error: incorrect value `bad-value` for codegen option `symbol-mangling-version` - one of: `legacy`, `v0` (RFC 2603), or `hashed` was expected diff --git a/tests/ui/symbol-mangling-version/bad-value.blank.stderr b/tests/ui/symbol-mangling-version/bad-value.blank.stderr index 0e70af5b8ffbe..95456587781e6 100644 --- a/tests/ui/symbol-mangling-version/bad-value.blank.stderr +++ b/tests/ui/symbol-mangling-version/bad-value.blank.stderr @@ -1,2 +1,2 @@ -error: incorrect value `` for codegen option `symbol-mangling-version` - either `legacy` or `v0` (RFC 2603) was expected +error: incorrect value `` for codegen option `symbol-mangling-version` - one of: `legacy`, `v0` (RFC 2603), or `hashed` was expected diff --git a/tests/ui/symbol-mangling-version/bad-value.no-value.stderr b/tests/ui/symbol-mangling-version/bad-value.no-value.stderr index 77013b72b6c1d..325e47a281fae 100644 --- a/tests/ui/symbol-mangling-version/bad-value.no-value.stderr +++ b/tests/ui/symbol-mangling-version/bad-value.no-value.stderr @@ -1,2 +1,2 @@ -error: codegen option `symbol-mangling-version` requires either `legacy` or `v0` (RFC 2603) (C symbol-mangling-version=) +error: codegen option `symbol-mangling-version` requires one of: `legacy`, `v0` (RFC 2603), or `hashed` (C symbol-mangling-version=) diff --git a/tests/ui/symbol-mangling-version/unstable.hashed.stderr b/tests/ui/symbol-mangling-version/unstable.hashed.stderr new file mode 100644 index 0000000000000..f2ae18290f261 --- /dev/null +++ b/tests/ui/symbol-mangling-version/unstable.hashed.stderr @@ -0,0 +1,2 @@ +error: `-C symbol-mangling-version=hashed` requires `-Z unstable-options` + diff --git a/tests/ui/symbol-mangling-version/unstable.rs b/tests/ui/symbol-mangling-version/unstable.rs index df87a39cdfbd1..42750a64574dc 100644 --- a/tests/ui/symbol-mangling-version/unstable.rs +++ b/tests/ui/symbol-mangling-version/unstable.rs @@ -1,6 +1,9 @@ -// revisions: legacy legacy-ok +// revisions: legacy legacy-ok hashed hashed-ok // [legacy] compile-flags: -Csymbol-mangling-version=legacy // [legacy-ok] check-pass // [legacy-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy +// [hashed] compile-flags: -Csymbol-mangling-version=hashed +// [hashed-ok] check-pass +// [hashed-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=hashed fn main() {} From 88e1620760413f43b2ae44684cb2ace869a15b1c Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Fri, 26 Jan 2024 05:03:07 +0000 Subject: [PATCH 237/676] 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 62bef6d52d994..6624672775f9d 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f6ee4bf3847277d6d6e2007ff664f8ea0895b11b +dd2559e08e1530806740931037d6bb83ef956161 From b8246e3847fcdea6f608ec7f24fdeabeabf08282 Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Fri, 26 Jan 2024 05:11:07 +0000 Subject: [PATCH 238/676] fmt --- src/tools/miri/src/machine.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 1cbde6590dde5..946887637fff8 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -10,8 +10,8 @@ use std::process; use either::Either; use rand::rngs::StdRng; -use rand::SeedableRng; use rand::Rng; +use rand::SeedableRng; use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -83,7 +83,8 @@ pub struct FrameExtra<'tcx> { impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Omitting `timing`, it does not support `Debug`. - let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } = self; + let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } = + self; f.debug_struct("FrameData") .field("borrow_tracker", borrow_tracker) .field("catch_unwind", catch_unwind) @@ -93,7 +94,8 @@ impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> { impl VisitProvenance for FrameExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } = self; + let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } = + self; catch_unwind.visit_provenance(visit); borrow_tracker.visit_provenance(visit); From 97a720b39b7e33a9201c7d7b71f44ac31a85f1bd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 25 Jan 2024 22:20:42 -0800 Subject: [PATCH 239/676] Rebase slice_group_by stabilization PR --- .../patches/0027-coretests-128bit-atomic-operations.patch | 2 +- compiler/rustc_passes/src/dead.rs | 2 +- compiler/rustc_passes/src/lib.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch index be29ae09bcfc6..271ca12eabbcd 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch @@ -21,7 +21,7 @@ index 897a5e9..331f66f 100644 -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(int_roundings)] - #![feature(slice_group_by)] + #![feature(split_array)] diff --git a/atomic.rs b/atomic.rs index b735957..ea728b6 100644 --- a/atomic.rs diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d3909ce3a1c1c..9be286744351f 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -917,7 +917,7 @@ impl<'tcx> DeadVisitor<'tcx> { return; } dead_codes.sort_by_key(|v| v.level); - for group in dead_codes[..].group_by(|a, b| a.level == b.level) { + for group in dead_codes[..].chunk_by(|a, b| a.level == b.level) { self.lint_at_single_level(&group, participle, Some(def_id), report_on); } } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 050a90efbdf6f..862b76b1f6048 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -11,7 +11,6 @@ #![feature(let_chains)] #![feature(map_try_insert)] #![feature(min_specialization)] -#![feature(slice_group_by)] #![feature(try_blocks)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] From 5dd6418010b9f47f536710bbc03adca786e03920 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 26 Jan 2024 07:44:18 +0100 Subject: [PATCH 240/676] mark a doctest with UB as no_run --- library/core/src/intrinsics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 76a53a9366a72..43124535ab5d8 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2531,7 +2531,7 @@ extern "rust-intrinsic" { /// or `false`, and the caller has to ensure sound behavior for both cases. /// In other words, the following code has *Undefined Behavior*: /// - /// ``` + /// ```no_run /// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] From 2318b0825cc2892a388b307d38389658f09ac3b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 26 Jan 2024 07:56:36 +0100 Subject: [PATCH 241/676] alidate the operand passed to is_val_statically_known --- src/tools/miri/src/shims/intrinsics/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 8edc0a4220d4a..e34fb118f7234 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -148,7 +148,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // ``` // Would not be considered UB, or the other way around (`is_val_statically_known(0)`). "is_val_statically_known" => { - let [_] = check_arg_count(args)?; + let [arg] = check_arg_count(args)?; + this.validate_operand(arg)?; let branch: bool = this.machine.rng.get_mut().gen(); this.write_scalar(Scalar::from_bool(branch), dest)?; } From 00ada8e30cb32a45dcac70630a8d4645a3ab393b Mon Sep 17 00:00:00 2001 From: Ardi <47633543+dev-ardi@users.noreply.github.com> Date: Fri, 26 Jan 2024 08:37:37 +0100 Subject: [PATCH 242/676] Update compiler/rustc_index/src/vec.rs Co-authored-by: Wesley Wiser --- compiler/rustc_index/src/vec.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 73265eb89961c..d876174e620f4 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -18,6 +18,7 @@ use crate::{Idx, IndexSlice}; /// you almost certainly want to use a [`newtype_index!`]-generated type instead. /// /// This allows to index the IndexVec with the new index type. +/// /// [`newtype_index!`]: ../macro.newtype_index.html #[derive(Clone, PartialEq, Eq, Hash)] #[repr(transparent)] From de8ccdbf80e7014092341096663a9dbba663bebb Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 26 Jan 2024 09:42:12 +0100 Subject: [PATCH 243/676] Clippy: Fix empty suggestion in from_over_into Co-authored-by: y21 <30553356+y21@users.noreply.github.com> --- src/tools/clippy/clippy_lints/src/from_over_into.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 93527bcdf5cee..1933a00891b0b 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -181,9 +181,6 @@ fn convert_to_from( let from = snippet_opt(cx, self_ty.span)?; let into = snippet_opt(cx, target_ty.span)?; - let return_type = matches!(sig.decl.output, FnRetTy::Return(_)) - .then_some(String::from("Self")) - .unwrap_or_default(); let mut suggestions = vec![ // impl Into for U -> impl From for U // ~~~~ ~~~~ @@ -200,10 +197,13 @@ fn convert_to_from( // fn into([mut] self) -> T -> fn into([mut] v: T) -> T // ~~~~ ~~~~ (self_ident.span, format!("val: {from}")), + ]; + + if let FnRetTy::Return(_) = sig.decl.output { // fn into(self) -> T -> fn into(self) -> Self // ~ ~~~~ - (sig.decl.output.span(), return_type), - ]; + suggestions.push((sig.decl.output.span(), String::from("Self"))); + } let mut finder = SelfFinder { cx, From 1fba58ed94fd056f28bd7c3ecaecdb806c629eae Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 26 Jan 2024 11:06:55 +0000 Subject: [PATCH 244/676] Update actions/checkout and actions/cache --- .github/workflows/abi-cafe.yml | 4 ++-- .github/workflows/audit.yml | 2 +- .github/workflows/main.yml | 18 +++++++++--------- .github/workflows/rustc.yml | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index bd3b051185b46..e6bf944f5527b 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -33,14 +33,14 @@ jobs: TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features if: matrix.os == 'ubuntu-latest' run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 3efdec4155932..b4f8ce0f5329d 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -10,7 +10,7 @@ jobs: audit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: | sed -i 's/components.*/components = []/' rust-toolchain echo 'profile = "minimal"' >> rust-toolchain diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9bbb18fc37fca..cf9a105538df4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Avoid installing rustc-dev run: | @@ -64,14 +64,14 @@ jobs: TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features if: matrix.os == 'ubuntu-latest' run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} @@ -138,7 +138,7 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features run: cat /proc/cpuinfo @@ -164,13 +164,13 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} @@ -221,10 +221,10 @@ jobs: TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-dist-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} @@ -276,7 +276,7 @@ jobs: cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Download all built artifacts uses: actions/download-artifact@v4 diff --git a/.github/workflows/rustc.yml b/.github/workflows/rustc.yml index 8085dc58263cc..930d025b73edc 100644 --- a/.github/workflows/rustc.yml +++ b/.github/workflows/rustc.yml @@ -9,13 +9,13 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} @@ -32,13 +32,13 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} From dc7ed1680c093ea7667f841ecaa7b89f205aef6f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 11 Jan 2024 22:23:46 +0100 Subject: [PATCH 245/676] Update to Cranelift 0.104 --- Cargo.lock | 140 +++++++++++++++++++++++++++++++++++++++-------------- Cargo.toml | 12 ++--- 2 files changed, 109 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d6a1200f5028..86bc7d0f067cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c22542c0b95bd3302f7ed6839869c561f2324bac2fd5e7e99f5cfa65fdc8b92" +checksum = "d819feeda4c420a18f1e28236ca0ce1177b22bf7c8a44ddee92dfe40de15bcf0" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3db903ef2e9c8a4de2ea6db5db052c7857282952f9df604aa55d169e6000d8" +checksum = "e9b8d03d5bdbca7e5f72b0e0a0f69933ed1f09e24be6c075aa6fe3f802b0cc0c" dependencies = [ "bumpalo", "cranelift-bforest", @@ -75,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6590feb5a1d6438f974bf6a5ac4dddf69fca14e1f07f3265d880f69e61a94463" +checksum = "a3fd3664e38e51649b17dc30cfdd561273fe2f590dcd013fb75d9eabc6272dfb" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7239038c56fafe77fddc8788fc8533dd6c474dc5bdc5637216404f41ba807330" +checksum = "4b031ec5e605828975952622b5a77d49126f20ffe88d33719a0af66b23a0fc36" [[package]] name = "cranelift-control" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7dc9c595341404d381d27a3d950160856b35b402275f0c3990cd1ad683c8053" +checksum = "fada054d017cf2ed8f7ed2336e0517fc1b19e6825be1790de9eb00c94788362b" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44e3ee532fc4776c69bcedf7e62f9632cbb3f35776fa9a525cdade3195baa3f7" +checksum = "177b6f94ae8de6348eb45bf977c79ab9e3c40fc3ac8cb7ed8109560ea39bee7d" [[package]] name = "cranelift-frontend" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a612c94d09e653662ec37681dc2d6fd2b9856e6df7147be0afc9aabb0abf19df" +checksum = "ebebd23a69a23e3ddea78e98ff3a2de222e88c8e045d81ef4a72f042e0d79dbd" dependencies = [ "cranelift-codegen", "log", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85db9830abeb1170b7d29b536ffd55af1d4d26ac8a77570b5d1aca003bf225cc" +checksum = "1571bfc14df8966d12c6121b5325026591a4b4009e22fea0fe3765ab7cd33b96" [[package]] name = "cranelift-jit" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4946271f1055e26544ef8c90fa24776f201566419dfac4b3962c39d5a804ff67" +checksum = "2f61e236d7622c3c43016e8b0f3ba27136e21ac7de328c7fda902e61db1de851" dependencies = [ "anyhow", "cranelift-codegen", @@ -138,14 +138,14 @@ dependencies = [ "region", "target-lexicon", "wasmtime-jit-icache-coherence", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "cranelift-module" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7e3bdae2597556e59edeb8ecb62eb32c7e054c4f042d393732902979db69c3" +checksum = "f30c6820342015c5009070e3e48d1da7b13521399de904663f1c84f5ee839657" dependencies = [ "anyhow", "cranelift-codegen", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301ef0edafeaeda5771a5d2db64ac53e1818ae3111220a185677025fe91db4a1" +checksum = "35a69c37e0c10b46fe5527f2397ac821046efbf5f7ec112c8b84df25712f465b" dependencies = [ "cranelift-codegen", "libc", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e0ee3d013728903e0c513c31afa389b559bfd4fe8a44f80335c799e3132a41" +checksum = "24425a329b4343177d5f1852243841dcec17f929d72c0e7f41262140155e55e7" dependencies = [ "anyhow", "cranelift-codegen", @@ -251,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -374,13 +374,13 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "16.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6d197fcc34ad32ed440e1f9552fd57d1f377d9699d31dee1b5b457322c1f8a" +checksum = "bdc26415bb89e9ccd3bdc498fef63aabf665c4c0dd710c107691deb9694955da" dependencies = [ "cfg-if", "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -411,7 +411,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -420,13 +429,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -435,38 +459,80 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml index c57e964168f4d..586ce2286f971 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.103", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.103" } -cranelift-module = { version = "0.103" } -cranelift-native = { version = "0.103" } -cranelift-jit = { version = "0.103", optional = true } -cranelift-object = { version = "0.103" } +cranelift-codegen = { version = "0.104", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.104" } +cranelift-module = { version = "0.104" } +cranelift-native = { version = "0.104" } +cranelift-jit = { version = "0.104", optional = true } +cranelift-object = { version = "0.104" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } From 96ebad0409f513ea60fb9bd2564247f6bbec30cc Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Fri, 26 Jan 2024 20:12:13 +0800 Subject: [PATCH 246/676] minor: update conflict extension detect logic --- editors/code/src/main.ts | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index f532a0ae1af5f..6935d529aad8b 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -25,7 +25,7 @@ export async function deactivate() { export async function activate( context: vscode.ExtensionContext, ): Promise { - conflictExtDetect(); + checkConflictingExtensions(); const ctx = new Ctx(context, createCommands(), fetchWorkspace()); // VS Code doesn't show a notification when an extension fails to activate @@ -192,7 +192,7 @@ function createCommands(): Record { }; } -function conflictExtDetect() { +function checkConflictingExtensions() { if (vscode.extensions.getExtension("rust-lang.rust")) { vscode.window .showWarningMessage( @@ -205,20 +205,12 @@ function conflictExtDetect() { } if (vscode.extensions.getExtension("panicbit.cargo")) { - const isRustAnalyzerCheckOnSave = vscode.workspace - .getConfiguration("rust-analyzer") - .get("checkOnSave"); - const isCargoAutomaticCheck = vscode.workspace - .getConfiguration("cargo") - .get("automaticCheck"); - if (isRustAnalyzerCheckOnSave && isCargoAutomaticCheck) { - vscode.window - .showWarningMessage( - `You have Cargo (panicbit.cargo) enabled with 'cargo.automaticCheck' set to true(default), ` + - 'you can disable it or set {"cargo.automaticCheck": false} in settings.json to avoid invoke cargo twice', - "Got it", - ) - .then(() => {}, console.error); - } + vscode.window + .showWarningMessage( + `You have both the rust-analyzer (rust-lang.rust-analyzer) and Cargo (panicbit.cargo) ` + + 'you can disable it or set {"cargo.automaticCheck": false} in settings.json to avoid invoking cargo twice', + "Got it", + ) + .then(() => {}, console.error); } } From 3269513eb0189946c40a67d98724b40321e6e9f3 Mon Sep 17 00:00:00 2001 From: "HTGAzureX1212." <39023054+HTGAzureX1212@users.noreply.github.com> Date: Fri, 26 Jan 2024 20:15:30 +0800 Subject: [PATCH 247/676] fix issue 120040 --- library/std/src/sys/pal/windows/fs.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 4248454368644..06a08ea22ebee 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -1068,6 +1068,27 @@ pub fn readdir(p: &Path) -> io::Result { unsafe { let mut wfd = mem::zeroed(); let find_handle = c::FindFirstFileW(path.as_ptr(), &mut wfd); + + // The status `ERROR_FILE_NOT_FOUND` is returned by the `FindFirstFileW` function + // if no matching files can be found, but not necessarily that the path to find the + // files in does not exist. + // + // Hence, a check for whether the path to search in exists is added when the last + // os error returned by Windows is `ERROR_FILE_NOT_FOUND` to handle this scenario. + // If that is the case, an empty `ReadDir` iterator is returned as it returns `None` + // in the initial `.next()` invocation because `ERROR_NO_MORE_FILES` would have been + // returned by the `FindNextFileW` function. + // + // See issue #120040: https://github.com/rust-lang/rust/issues/120040. + let last_error = Error::last_os_error(); + if last_error.raw_os_error().unwrap() == c::ERROR_FILE_NOT_FOUND && p.exists() { + return Ok(ReadDir { + handle: FindNextFileHandle(file_handle), + root: Arc::new(root), + first: None, + }); + } + if find_handle != c::INVALID_HANDLE_VALUE { Ok(ReadDir { handle: FindNextFileHandle(find_handle), From 1f994c7695e9abc5953ed107de4494f83cca33ae Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:15:46 +0000 Subject: [PATCH 248/676] Fix outdated comment on Box --- library/alloc/src/boxed.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 6977681e5a397..2e32101840780 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -191,8 +191,7 @@ mod thin; #[fundamental] #[stable(feature = "rust1", since = "1.0.0")] // The declaration of the `Box` struct must be kept in sync with the -// `alloc::alloc::box_free` function or ICEs will happen. See the comment -// on `box_free` for more details. +// compiler or ICEs will happen. pub struct Box< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, From 8f89e57e9f7fe4a2fccf57161aea39a4e48b6a75 Mon Sep 17 00:00:00 2001 From: "HTGAzureX1212." <39023054+HTGAzureX1212@users.noreply.github.com> Date: Fri, 26 Jan 2024 20:27:20 +0800 Subject: [PATCH 249/676] remove redundant call to Error::last_os_error --- library/std/src/sys/pal/windows/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 06a08ea22ebee..b5976b87be210 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -1096,7 +1096,7 @@ pub fn readdir(p: &Path) -> io::Result { first: Some(wfd), }) } else { - Err(Error::last_os_error()) + Err(last_error) } } } From 2241d1618960a2d192b2874e925fa51afeb8a83b Mon Sep 17 00:00:00 2001 From: "HTGAzureX1212." <39023054+HTGAzureX1212@users.noreply.github.com> Date: Fri, 26 Jan 2024 20:34:13 +0800 Subject: [PATCH 250/676] fix --- library/std/src/sys/pal/windows/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index b5976b87be210..38835db7649de 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -1081,9 +1081,9 @@ pub fn readdir(p: &Path) -> io::Result { // // See issue #120040: https://github.com/rust-lang/rust/issues/120040. let last_error = Error::last_os_error(); - if last_error.raw_os_error().unwrap() == c::ERROR_FILE_NOT_FOUND && p.exists() { + if last_error.raw_os_error().unwrap() == c::ERROR_FILE_NOT_FOUND as i32 && p.exists() { return Ok(ReadDir { - handle: FindNextFileHandle(file_handle), + handle: FindNextFileHandle(find_handle), root: Arc::new(root), first: None, }); From bdf7404b43d683accd29c20c880c51c85ceaaccd Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 26 Jan 2024 14:46:17 +0100 Subject: [PATCH 251/676] Update codegen test for LLVM 18 --- tests/codegen/pow_of_two.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/pow_of_two.rs b/tests/codegen/pow_of_two.rs index a8c0550e33263..372360dfd12c7 100644 --- a/tests/codegen/pow_of_two.rs +++ b/tests/codegen/pow_of_two.rs @@ -4,7 +4,7 @@ #[no_mangle] pub fn a(exp: u32) -> u64 { // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64 - // CHECK: %{{[^ ]+}} = zext i32 %exp to i64 + // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64 // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}} // CHECK: ret i64 %{{[^ ]+}} 2u64.pow(exp) @@ -14,7 +14,7 @@ pub fn a(exp: u32) -> u64 { #[no_mangle] pub fn b(exp: u32) -> i64 { // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64 - // CHECK: %{{[^ ]+}} = zext i32 %exp to i64 + // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64 // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}} // CHECK: ret i64 %{{[^ ]+}} 2i64.pow(exp) From 604c8a7cf80eca33bd078d6b45faaa808ef9ecd8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 26 Jan 2024 14:19:11 +0000 Subject: [PATCH 252/676] Accept [u8; N] bitmasks in simd_select_bitmask Fixes rust-lang/rustc_codegen_cranelift#1446 --- build_system/tests.rs | 4 +-- ...nable-the-exposed_provenance-feature.patch | 22 -------------- src/intrinsics/simd.rs | 30 ++++++++++++++++++- 3 files changed, 31 insertions(+), 25 deletions(-) delete mode 100644 patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch diff --git a/build_system/tests.rs b/build_system/tests.rs index cb7b2454cd5ed..20f6d70a58bf6 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -133,8 +133,8 @@ pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github( "rust-lang", "portable-simd", - "4825b2a64d765317066948867e8714674419359b", - "9e67d07c00f5fb0b", + "97007cc2e70df8c97326ce896a79e2f0ce4dd98b", + "e54a16035cedf205", "portable-simd", ); diff --git a/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch b/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch deleted file mode 100644 index b8c0783f52430..0000000000000 --- a/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch +++ /dev/null @@ -1,22 +0,0 @@ -From a101a43b795431ce617e7782afb451f4853afc00 Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Thu, 7 Dec 2023 14:51:35 +0000 -Subject: [PATCH] Enable the exposed_provenance feature - ---- - crates/core_simd/tests/pointers.rs | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/crates/core_simd/tests/pointers.rs b/crates/core_simd/tests/pointers.rs -index 0ae8f83..06620d6 100644 ---- a/crates/core_simd/tests/pointers.rs -+++ b/crates/core_simd/tests/pointers.rs -@@ -1,4 +1,4 @@ --#![feature(portable_simd, strict_provenance)] -+#![feature(exposed_provenance, portable_simd, strict_provenance)] - - use core_simd::simd::{Simd, SimdConstPtr, SimdMutPtr}; - --- -2.34.1 - diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index dfa54b775aa41..ebdc744bcd833 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -822,7 +822,35 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); let lane_layout = fx.layout_of(lane_ty); - let m = m.load_scalar(fx); + let expected_int_bits = lane_count.max(8); + let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64); + + let m = match m.layout().ty.kind() { + ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => m.load_scalar(fx), + ty::Array(elem, len) + if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) + && len.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) + == Some(expected_bytes) => + { + m.force_stack(fx).0.load( + fx, + Type::int(expected_int_bits as u16).unwrap(), + MemFlags::trusted(), + ) + } + _ => { + fx.tcx.dcx().span_fatal( + span, + format!( + "invalid monomorphization of `simd_select_bitmask` intrinsic: \ + cannot accept `{}` as mask, expected `u{}` or `[u8; {}]`", + ret.layout().ty, + expected_int_bits, + expected_bytes + ), + ); + } + }; for lane in 0..lane_count { let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64); From a39a2f73d6eb912902ca62d160b158e8907b6622 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 26 Jan 2024 15:26:03 +0100 Subject: [PATCH 253/676] next-solver: normalize in `LoweredTy::from_raw` --- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 10 +++++++++- tests/ui/for/issue-20605.next.stderr | 20 +++++++++---------- .../next-solver/normalize-path-for-method.rs | 18 +++++++++++++++++ .../recursive-self-normalization-2.rs | 1 + .../recursive-self-normalization-2.stderr | 11 +++++++++- .../overflow/recursive-self-normalization.rs | 1 + .../recursive-self-normalization.stderr | 11 +++++++++- 7 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 tests/ui/traits/next-solver/normalize-path-for-method.rs diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 18f547be2a71c..449de631f5a20 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -369,6 +369,14 @@ pub struct LoweredTy<'tcx> { impl<'tcx> LoweredTy<'tcx> { pub fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> { - LoweredTy { raw, normalized: fcx.normalize(span, raw) } + // FIXME(-Znext-solver): We're still figuring out how to best handle + // normalization and this doesn't feel too great. We should look at this + // code again before stabilizing it. + let normalized = if fcx.next_trait_solver() { + fcx.try_structurally_resolve_type(span, raw) + } else { + fcx.normalize(span, raw) + }; + LoweredTy { raw, normalized } } } diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 28dbdf4c374c0..3d753b9c8b884 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -34,15 +34,11 @@ error: the type `&mut as IntoIterator>::IntoIte LL | for item in *things { *item = 0 } | ^^^^^^^ -error[E0277]: the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time - --> $DIR/issue-20605.rs:5:9 +error: the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed + --> $DIR/issue-20605.rs:5:17 | LL | for item in *things { *item = 0 } - | ^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `< as IntoIterator>::IntoIter as Iterator>::Item` - = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature + | ^^^^^^^ error[E0277]: the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time --> $DIR/issue-20605.rs:5:5 @@ -54,11 +50,15 @@ LL | for item in *things { *item = 0 } note: required by a bound in `None` --> $SRC_DIR/core/src/option.rs:LL:COL -error: the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed - --> $DIR/issue-20605.rs:5:17 +error[E0277]: the size for values of type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time + --> $DIR/issue-20605.rs:5:9 | LL | for item in *things { *item = 0 } - | ^^^^^^^ + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `< as IntoIterator>::IntoIter as Iterator>::Item` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature error[E0614]: type `< as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced --> $DIR/issue-20605.rs:5:27 diff --git a/tests/ui/traits/next-solver/normalize-path-for-method.rs b/tests/ui/traits/next-solver/normalize-path-for-method.rs new file mode 100644 index 0000000000000..b95454306cd69 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-path-for-method.rs @@ -0,0 +1,18 @@ +// compile-flags: -Znext-solver +// check-pass + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +struct Foo; +impl Foo { + fn new() -> Self { Foo } +} + +fn main() { + ::Assoc::new(); +} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index 71b1502d775fc..932826519b7d2 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -16,6 +16,7 @@ fn test::Assoc2> + Foo2::Assoc //~^ ERROR overflow evaluating the requirement `::Assoc1 == _` //~| ERROR overflow evaluating the requirement `::Assoc1 == _` //~| ERROR overflow evaluating the requirement `::Assoc1 == _` + //~| ERROR overflow evaluating the requirement `::Assoc1 == _` //~| ERROR overflow evaluating the requirement `::Assoc1: Bar` } 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 bad6820f7389d..e4f1f9cf02255 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 @@ -1,3 +1,11 @@ +error[E0275]: overflow evaluating the requirement `::Assoc1 == _` + --> $DIR/recursive-self-normalization-2.rs:15:17 + | +LL | needs_bar::(); + | ^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`) + error[E0275]: overflow evaluating the requirement `::Assoc1: Bar` --> $DIR/recursive-self-normalization-2.rs:15:17 | @@ -35,7 +43,8 @@ LL | needs_bar::(); | ^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs index 809a6a59ca6aa..32672c08c7e07 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs @@ -12,6 +12,7 @@ fn test::Assoc>>() { //~^ ERROR overflow evaluating the requirement `::Assoc == _` //~| ERROR overflow evaluating the requirement `::Assoc == _` //~| ERROR overflow evaluating the requirement `::Assoc == _` + //~| ERROR overflow evaluating the requirement `::Assoc == _` //~| ERROR overflow evaluating the requirement `::Assoc: 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 80005d344ba39..da5c8bde568d2 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr @@ -1,3 +1,11 @@ +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/recursive-self-normalization.rs:11:17 + | +LL | needs_bar::(); + | ^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`) + error[E0275]: overflow evaluating the requirement `::Assoc: Bar` --> $DIR/recursive-self-normalization.rs:11:17 | @@ -35,7 +43,8 @@ LL | needs_bar::(); | ^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0275`. From e87b8c7f34b9890503f59c93fa4805d1920f2b9c Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 26 Jan 2024 15:49:05 +0100 Subject: [PATCH 254/676] move alias-relate tests --- .../{ => alias-relate}/alias_eq_cant_be_furthur_normalized.rs | 0 .../alias_eq_dont_use_normalizes_to_if_substs_eq.rs | 0 .../ui/traits/next-solver/{ => alias-relate}/alias_eq_simple.rs | 0 .../{ => alias-relate}/alias_eq_substs_eq_not_intercrate.rs | 0 .../{ => alias-relate}/alias_eq_substs_eq_not_intercrate.stderr | 0 .../ui/traits/next-solver/{ => alias-relate}/tait-eq-proj-2.rs | 2 +- tests/ui/traits/next-solver/{ => alias-relate}/tait-eq-proj.rs | 0 tests/ui/traits/next-solver/{ => alias-relate}/tait-eq-tait.rs | 0 8 files changed, 1 insertion(+), 1 deletion(-) rename tests/ui/traits/next-solver/{ => alias-relate}/alias_eq_cant_be_furthur_normalized.rs (100%) rename tests/ui/traits/next-solver/{ => alias-relate}/alias_eq_dont_use_normalizes_to_if_substs_eq.rs (100%) rename tests/ui/traits/next-solver/{ => alias-relate}/alias_eq_simple.rs (100%) rename tests/ui/traits/next-solver/{ => alias-relate}/alias_eq_substs_eq_not_intercrate.rs (100%) rename tests/ui/traits/next-solver/{ => alias-relate}/alias_eq_substs_eq_not_intercrate.stderr (100%) rename tests/ui/traits/next-solver/{ => alias-relate}/tait-eq-proj-2.rs (84%) rename tests/ui/traits/next-solver/{ => alias-relate}/tait-eq-proj.rs (100%) rename tests/ui/traits/next-solver/{ => alias-relate}/tait-eq-tait.rs (100%) diff --git a/tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs b/tests/ui/traits/next-solver/alias-relate/alias_eq_cant_be_furthur_normalized.rs similarity index 100% rename from tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs rename to tests/ui/traits/next-solver/alias-relate/alias_eq_cant_be_furthur_normalized.rs diff --git a/tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs b/tests/ui/traits/next-solver/alias-relate/alias_eq_dont_use_normalizes_to_if_substs_eq.rs similarity index 100% rename from tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs rename to tests/ui/traits/next-solver/alias-relate/alias_eq_dont_use_normalizes_to_if_substs_eq.rs diff --git a/tests/ui/traits/next-solver/alias_eq_simple.rs b/tests/ui/traits/next-solver/alias-relate/alias_eq_simple.rs similarity index 100% rename from tests/ui/traits/next-solver/alias_eq_simple.rs rename to tests/ui/traits/next-solver/alias-relate/alias_eq_simple.rs diff --git a/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs b/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.rs similarity index 100% rename from tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs rename to tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.rs diff --git a/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr similarity index 100% rename from tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr rename to tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr diff --git a/tests/ui/traits/next-solver/tait-eq-proj-2.rs b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs similarity index 84% rename from tests/ui/traits/next-solver/tait-eq-proj-2.rs rename to tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs index a3df053dd8325..915643f1d2a89 100644 --- a/tests/ui/traits/next-solver/tait-eq-proj-2.rs +++ b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs @@ -3,7 +3,7 @@ #![feature(type_alias_impl_trait)] -// Similar to tests/ui/traits/next-solver/tait-eq-proj.rs +// Similar to tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs // but check the alias-sub relation in the other direction. type Tait = impl Iterator; diff --git a/tests/ui/traits/next-solver/tait-eq-proj.rs b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs similarity index 100% rename from tests/ui/traits/next-solver/tait-eq-proj.rs rename to tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs diff --git a/tests/ui/traits/next-solver/tait-eq-tait.rs b/tests/ui/traits/next-solver/alias-relate/tait-eq-tait.rs similarity index 100% rename from tests/ui/traits/next-solver/tait-eq-tait.rs rename to tests/ui/traits/next-solver/alias-relate/tait-eq-tait.rs From 7b6ac8bf21d6346c90bc8ea1d2557690a63fbf86 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 26 Jan 2024 15:51:20 +0100 Subject: [PATCH 255/676] remove unnecessary test --- .../traits/next-solver/temporary-ambiguity.rs | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 tests/ui/traits/next-solver/temporary-ambiguity.rs diff --git a/tests/ui/traits/next-solver/temporary-ambiguity.rs b/tests/ui/traits/next-solver/temporary-ambiguity.rs deleted file mode 100644 index 6102de7e446d6..0000000000000 --- a/tests/ui/traits/next-solver/temporary-ambiguity.rs +++ /dev/null @@ -1,22 +0,0 @@ -// compile-flags: -Znext-solver -// check-pass - -// Checks that we don't explode when we assemble >1 candidate for a goal. - -struct Wrapper(T); - -trait Foo {} - -impl Foo for Wrapper {} - -impl Foo for Wrapper<()> {} - -fn needs_foo(_: impl Foo) {} - -fn main() { - let mut x = Default::default(); - let w = Wrapper(x); - needs_foo(w); - x = 1; - let _ = x; -} From e17f91dd8b49a319ec034a6d738e7b396e3ec879 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 26 Jan 2024 23:53:51 +0800 Subject: [PATCH 256/676] Classify closure arguments in refutable pattern in argument error --- .../rustc_mir_build/src/thir/pattern/check_match.rs | 11 ++++++++++- .../pattern/usefulness/refutable-pattern-in-fn-arg.rs | 2 +- .../usefulness/refutable-pattern-in-fn-arg.stderr | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index ce75a2831a51e..435ea3dc3bbc7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -47,9 +47,18 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err }; visitor.visit_expr(&thir[expr]); + let origin = match tcx.def_kind(def_id) { + DefKind::AssocFn | DefKind::Fn => "function argument", + DefKind::Closure => "closure argument", + // other types of MIR don't have function parameters, and we don't need to + // categorize those for the irrefutable check. + _ if thir.params.is_empty() => "", + kind => bug!("unexpected function parameters in THIR: {kind:?} {def_id:?}"), + }; + for param in thir.params.iter() { if let Some(box ref pattern) = param.pat { - visitor.check_binding_is_irrefutable(pattern, "function argument", None, None); + visitor.check_binding_is_irrefutable(pattern, origin, None, None); } } visitor.error diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs index 4203dd94d43aa..51ff641509df5 100644 --- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs @@ -1,6 +1,6 @@ fn main() { let f = |3: isize| println!("hello"); - //~^ ERROR refutable pattern in function argument + //~^ ERROR refutable pattern in closure argument //~| `..=2_isize` and `4_isize..` not covered f(4); } diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr index bd6c5002e63e8..be119d27ab254 100644 --- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr @@ -1,4 +1,4 @@ -error[E0005]: refutable pattern in function argument +error[E0005]: refutable pattern in closure argument --> $DIR/refutable-pattern-in-fn-arg.rs:2:14 | LL | let f = |3: isize| println!("hello"); From cda358857214bb5a2b3df4f011102ffee3843a72 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Sep 2023 08:15:34 +0200 Subject: [PATCH 257/676] make matching on NaN a hard error --- .../rustc_middle/src/mir/interpret/value.rs | 4 +- compiler/rustc_middle/src/ty/consts/int.rs | 71 ++++++++++------ compiler/rustc_mir_build/messages.ftl | 4 + compiler/rustc_mir_build/src/errors.rs | 9 ++ .../src/thir/pattern/const_to_pat.rs | 35 +++++--- .../issue-6804-nan-match.rs | 32 ++++++++ .../issue-6804-nan-match.stderr | 82 +++++++++++++++++++ .../issue-6804.rs | 21 ----- .../issue-6804.stderr | 25 ------ 9 files changed, 197 insertions(+), 86 deletions(-) create mode 100644 tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs create mode 100644 tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr delete mode 100644 tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs delete mode 100644 tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 5ecff04f3ae35..e937c17c8acec 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -418,8 +418,8 @@ impl<'tcx, Prov: Provenance> Scalar { #[inline] pub fn to_float(self) -> InterpResult<'tcx, F> { - // Going through `to_uint` to check size and truncation. - Ok(F::from_bits(self.to_uint(Size::from_bits(F::BITS))?)) + // Going through `to_bits` to check size and truncation. + Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?)) } #[inline] diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 310cf113b11b6..d810e358f8562 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -249,11 +249,6 @@ impl ScalarInt { } } - #[inline] - pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result { - Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64) - } - /// Tries to convert the `ScalarInt` to an unsigned integer of the given size. /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the /// `ScalarInt`s size in that case. @@ -262,24 +257,12 @@ impl ScalarInt { self.to_bits(size) } - // Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt` - // in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size` - // value of the `ScalarInt` in that case. - #[inline] - pub fn try_to_bool(self) -> Result { - match self.try_to_u8()? { - 0 => Ok(false), - 1 => Ok(true), - _ => Err(self.size()), - } - } - // Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt` // in not equal to `Size { raw: 1 }` and returns the `size` value of the `ScalarInt` in // that case. #[inline] pub fn try_to_u8(self) -> Result { - self.to_bits(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap()) + self.try_to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to `u16`. Fails if the size of the `ScalarInt` @@ -287,7 +270,7 @@ impl ScalarInt { /// that case. #[inline] pub fn try_to_u16(self) -> Result { - self.to_bits(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap()) + self.try_to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to `u32`. Fails if the `size` of the `ScalarInt` @@ -295,7 +278,7 @@ impl ScalarInt { /// that case. #[inline] pub fn try_to_u32(self) -> Result { - self.to_bits(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap()) + self.try_to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to `u64`. Fails if the `size` of the `ScalarInt` @@ -303,7 +286,7 @@ impl ScalarInt { /// that case. #[inline] pub fn try_to_u64(self) -> Result { - self.to_bits(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap()) + self.try_to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to `u128`. Fails if the `size` of the `ScalarInt` @@ -311,7 +294,24 @@ impl ScalarInt { /// that case. #[inline] pub fn try_to_u128(self) -> Result { - self.to_bits(Size::from_bits(128)) + self.try_to_uint(Size::from_bits(128)) + } + + #[inline] + pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result { + self.try_to_uint(tcx.data_layout.pointer_size).map(|v| u64::try_from(v).unwrap()) + } + + // Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt` + // in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size` + // value of the `ScalarInt` in that case. + #[inline] + pub fn try_to_bool(self) -> Result { + match self.try_to_u8()? { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(self.size()), + } } /// Tries to convert the `ScalarInt` to a signed integer of the given size. @@ -357,6 +357,27 @@ impl ScalarInt { pub fn try_to_i128(self) -> Result { self.try_to_int(Size::from_bits(128)) } + + #[inline] + pub fn try_to_target_isize(&self, tcx: TyCtxt<'_>) -> Result { + self.try_to_int(tcx.data_layout.pointer_size).map(|v| i64::try_from(v).unwrap()) + } + + #[inline] + pub fn try_to_float(self) -> Result { + // Going through `to_uint` to check size and truncation. + Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?)) + } + + #[inline] + pub fn try_to_f32(self) -> Result { + self.try_to_float() + } + + #[inline] + pub fn try_to_f64(self) -> Result { + self.try_to_float() + } } macro_rules! from { @@ -399,11 +420,7 @@ impl TryFrom for bool { type Error = Size; #[inline] fn try_from(int: ScalarInt) -> Result { - int.to_bits(Size::from_bytes(1)).and_then(|u| match u { - 0 => Ok(false), - 1 => Ok(true), - _ => Err(Size::from_bytes(1)), - }) + int.try_to_bool() } } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 9631b72f20c54..14d09535d7dba 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -232,6 +232,10 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa .note = mutating layout constrained fields cannot statically be checked for valid values .label = mutation of layout constrained field +mir_build_nan_pattern = cannot use NaN in patterns + .note = NaNs compare inequal to everything, even themselves, so this pattern would never match + .help = try using the `is_nan` method instead + mir_build_non_const_path = runtime values cannot be referenced in patterns mir_build_non_empty_never_pattern = diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e1b998b24718c..eef0505198505 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -780,6 +780,15 @@ pub struct UnsizedPattern<'tcx> { pub non_sm_ty: Ty<'tcx>, } +#[derive(Diagnostic)] +#[diag(mir_build_nan_pattern)] +#[note] +#[help] +pub struct NaNPattern { + #[primary_span] + pub span: Span, +} + #[derive(LintDiagnostic)] #[diag(mir_build_float_pattern)] pub struct FloatPattern; diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 22305f03a769d..cb67bc6b0b3c0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,3 +1,4 @@ +use rustc_apfloat::Float; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::Idx; @@ -16,7 +17,7 @@ use std::cell::Cell; use super::PatCtxt; use crate::errors::{ - FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch, + FloatPattern, IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, }; @@ -317,16 +318,6 @@ impl<'tcx> ConstToPat<'tcx> { let param_env = self.param_env; let kind = match ty.kind() { - ty::Float(_) => { - self.saw_const_match_lint.set(true); - tcx.emit_node_span_lint( - lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, - id, - span, - FloatPattern, - ); - return Err(FallbackToOpaqueConst); - } // If the type is not structurally comparable, just emit the constant directly, // causing the pattern match code to treat it opaquely. // FIXME: This code doesn't emit errors itself, the caller emits the errors. @@ -486,6 +477,28 @@ impl<'tcx> ConstToPat<'tcx> { } } }, + ty::Float(flt) => { + let v = cv.unwrap_leaf(); + let is_nan = match flt { + ty::FloatTy::F32 => v.try_to_f32().unwrap().is_nan(), + ty::FloatTy::F64 => v.try_to_f64().unwrap().is_nan(), + }; + if is_nan { + // NaNs are not ever equal to anything so they make no sense as patterns. + // Also see . + let e = tcx.dcx().emit_err(NaNPattern { span }); + self.saw_const_match_error.set(Some(e)); + } else { + self.saw_const_match_lint.set(true); + tcx.emit_node_span_lint( + lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, + id, + span, + FloatPattern, + ); + } + return Err(FallbackToOpaqueConst); + } ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => { // The raw pointers we see here have been "vetted" by valtree construction to be // just integers, so we simply allow them. diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs new file mode 100644 index 0000000000000..c5bca8c970dae --- /dev/null +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs @@ -0,0 +1,32 @@ +// Matching against NaN should result in an error +#![feature(exclusive_range_pattern)] +#![allow(unused)] +#![allow(illegal_floating_point_literal_pattern)] + +const NAN: f64 = f64::NAN; + +fn main() { + let x = NAN; + match x { + NAN => {}, //~ ERROR cannot use NaN in patterns + _ => {}, + }; + + match [x, 1.0] { + [NAN, _] => {}, //~ ERROR cannot use NaN in patterns + _ => {}, + }; + + // Also cover range patterns + match x { + NAN..=1.0 => {}, //~ ERROR cannot use NaN in patterns + //~^ ERROR lower range bound must be less than or equal to upper + -1.0..=NAN => {}, //~ ERROR cannot use NaN in patterns + //~^ ERROR lower range bound must be less than or equal to upper + NAN.. => {}, //~ ERROR cannot use NaN in patterns + //~^ ERROR lower range bound must be less than or equal to upper + ..NAN => {}, //~ ERROR cannot use NaN in patterns + //~^ ERROR lower range bound must be less than upper + _ => {}, + }; +} diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr new file mode 100644 index 0000000000000..deda07150c52d --- /dev/null +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr @@ -0,0 +1,82 @@ +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:11:9 + | +LL | NAN => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:16:10 + | +LL | [NAN, _] => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:22:9 + | +LL | NAN..=1.0 => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/issue-6804-nan-match.rs:22:9 + | +LL | NAN..=1.0 => {}, + | ^^^^^^^^^ lower bound larger than upper bound + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:24:16 + | +LL | -1.0..=NAN => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/issue-6804-nan-match.rs:24:9 + | +LL | -1.0..=NAN => {}, + | ^^^^^^^^^^ lower bound larger than upper bound + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:26:9 + | +LL | NAN.. => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/issue-6804-nan-match.rs:26:9 + | +LL | NAN.. => {}, + | ^^^^^ lower bound larger than upper bound + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:28:11 + | +LL | ..NAN => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error[E0579]: lower range bound must be less than upper + --> $DIR/issue-6804-nan-match.rs:28:9 + | +LL | ..NAN => {}, + | ^^^^^ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0030, E0579. +For more information about an error, try `rustc --explain E0030`. diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs deleted file mode 100644 index 0260caa82cb1d..0000000000000 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Matching against NaN should result in a warning - -#![allow(unused)] -#![deny(illegal_floating_point_literal_pattern)] - -const NAN: f64 = f64::NAN; - -fn main() { - let x = NAN; - match x { - NAN => {}, //~ ERROR floating-point types cannot be used - //~| WARN this was previously accepted by the compiler but is being phased out - _ => {}, - }; - - match [x, 1.0] { - [NAN, _] => {}, //~ ERROR floating-point types cannot be used - //~| WARN this was previously accepted by the compiler but is being phased out - _ => {}, - }; -} diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr deleted file mode 100644 index f37255d0828cd..0000000000000 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: floating-point types cannot be used in patterns - --> $DIR/issue-6804.rs:11:9 - | -LL | NAN => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 -note: the lint level is defined here - --> $DIR/issue-6804.rs:4:9 - | -LL | #![deny(illegal_floating_point_literal_pattern)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: floating-point types cannot be used in patterns - --> $DIR/issue-6804.rs:17:10 - | -LL | [NAN, _] => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: aborting due to 2 previous errors - From 1254ee48c458a5fe8fc1847539169df013098e05 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 6 Jan 2024 14:39:51 +0100 Subject: [PATCH 258/676] remove illegal_floating_point_literal_pattern lint --- compiler/rustc_lint/src/lib.rs | 4 + compiler/rustc_lint_defs/src/builtin.rs | 50 ------- compiler/rustc_mir_build/messages.ftl | 2 - compiler/rustc_mir_build/src/errors.rs | 4 - .../src/thir/pattern/const_to_pat.rs | 12 +- .../tests/ui/expect_tool_lint_rfc_2383.rs | 16 +-- .../tests/ui/expect_tool_lint_rfc_2383.stderr | 16 +-- .../lints/expect-tool-lint-rfc-2383.rs | 7 +- .../lints/expect-tool-lint-rfc-2383.stderr | 6 +- .../array-slice-vec/vec-matching-autoslice.rs | 1 - tests/ui/binding/match-range.rs | 1 - .../half-open-range-pats-exhaustive-fail.rs | 1 - ...alf-open-range-pats-exhaustive-fail.stderr | 136 +++++++++--------- .../half-open-range-pats-semantics.rs | 1 - .../half-open-range-pats-thir-lower-empty.rs | 1 - ...lf-open-range-pats-thir-lower-empty.stderr | 26 ++-- tests/ui/lint/issue-86600-lint-twice.rs | 15 -- tests/ui/lint/issue-86600-lint-twice.stderr | 12 -- .../expect_tool_lint_rfc_2383.rs | 16 +-- .../expect_tool_lint_rfc_2383.stderr | 8 +- tests/ui/match/issue-41255.rs | 50 ------- tests/ui/match/issue-41255.stderr | 115 --------------- tests/ui/parser/issues/issue-7222.rs | 1 - tests/ui/pattern/usefulness/floats.rs | 1 - tests/ui/pattern/usefulness/floats.stderr | 18 +-- .../usefulness/non-exhaustive-match.rs | 2 - .../usefulness/non-exhaustive-match.stderr | 20 +-- .../issue-6804-nan-match.rs | 1 - .../issue-6804-nan-match.stderr | 20 +-- tests/ui/union/union-pat-refutability.rs | 1 - 30 files changed, 143 insertions(+), 421 deletions(-) delete mode 100644 tests/ui/lint/issue-86600-lint-twice.rs delete mode 100644 tests/ui/lint/issue-86600-lint-twice.stderr delete mode 100644 tests/ui/match/issue-41255.rs delete mode 100644 tests/ui/match/issue-41255.stderr diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 1d9ce10bcaf38..0a15671e68692 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -516,6 +516,10 @@ fn register_builtins(store: &mut LintStore) { "converted into hard error, see PR #118649 \ for more information", ); + store.register_removed( + "illegal_floating_point_literal_pattern", + "no longer a warning, float patterns behave the same as `==`", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e6d837ecd92bd..07c0e75a71c96 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -45,7 +45,6 @@ declare_lint_pass! { FUZZY_PROVENANCE_CASTS, HIDDEN_GLOB_REEXPORTS, ILL_FORMED_ATTRIBUTE_INPUT, - ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, INCOMPLETE_INCLUDE, INDIRECT_STRUCTURAL_MATCH, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, @@ -1873,55 +1872,6 @@ declare_lint! { }; } -declare_lint! { - /// The `illegal_floating_point_literal_pattern` lint detects - /// floating-point literals used in patterns. - /// - /// ### Example - /// - /// ```rust - /// let x = 42.0; - /// - /// match x { - /// 5.0 => {} - /// _ => {} - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Previous versions of the compiler accepted floating-point literals in - /// patterns, but it was later determined this was a mistake. The - /// semantics of comparing floating-point values may not be clear in a - /// pattern when contrasted with "structural equality". Typically you can - /// work around this by using a [match guard], such as: - /// - /// ```rust - /// # let x = 42.0; - /// - /// match x { - /// y if y == 5.0 => {} - /// _ => {} - /// } - /// ``` - /// - /// This is a [future-incompatible] lint to transition this to a hard - /// error in the future. See [issue #41620] for more details. - /// - /// [issue #41620]: https://github.com/rust-lang/rust/issues/41620 - /// [match guard]: https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, - Warn, - "floating-point literals cannot be used in patterns", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #41620 ", - }; -} - declare_lint! { /// The `unstable_name_collisions` lint detects that you have used a name /// that the standard library plans to add in the future. diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 14d09535d7dba..8a6ccdb857829 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -107,8 +107,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior .label = use of extern static -mir_build_float_pattern = floating-point types cannot be used in patterns - mir_build_indirect_structural_match = to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]` diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index eef0505198505..641822ae202aa 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -789,10 +789,6 @@ pub struct NaNPattern { pub span: Span, } -#[derive(LintDiagnostic)] -#[diag(mir_build_float_pattern)] -pub struct FloatPattern; - #[derive(LintDiagnostic)] #[diag(mir_build_pointer_pattern)] pub struct PointerPattern; diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index cb67bc6b0b3c0..9d3a9bf6745e7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -17,7 +17,7 @@ use std::cell::Cell; use super::PatCtxt; use crate::errors::{ - FloatPattern, IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, + IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, }; @@ -488,16 +488,10 @@ impl<'tcx> ConstToPat<'tcx> { // Also see . let e = tcx.dcx().emit_err(NaNPattern { span }); self.saw_const_match_error.set(Some(e)); + return Err(FallbackToOpaqueConst); } else { - self.saw_const_match_lint.set(true); - tcx.emit_node_span_lint( - lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, - id, - span, - FloatPattern, - ); + PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) } } - return Err(FallbackToOpaqueConst); } ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => { // The raw pointers we see here have been "vetted" by valtree construction to be diff --git a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs index 3811421dc7158..72097bfabd726 100644 --- a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs +++ b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs @@ -20,12 +20,8 @@ mod rustc_ok { pub fn rustc_lints() { let x = 42.0; - #[expect(illegal_floating_point_literal_pattern)] - match x { - 5.0 => {} - 6.0 => {} - _ => {} - } + #[expect(invalid_nan_comparisons)] + let _b = x == f32::NAN; } } @@ -38,13 +34,9 @@ mod rustc_warn { pub fn rustc_lints() { let x = 42; - #[expect(illegal_floating_point_literal_pattern)] + #[expect(invalid_nan_comparisons)] //~^ ERROR: this lint expectation is unfulfilled - match x { - 5 => {} - 6 => {} - _ => {} - } + let _b = x == 5; } } diff --git a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr index 3f8d0b7243620..2a418d8456635 100644 --- a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr +++ b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -1,5 +1,5 @@ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:35:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:31:14 | LL | #[expect(dead_code)] | ^^^^^^^^^ @@ -8,31 +8,31 @@ LL | #[expect(dead_code)] = help: to override `-D warnings` add `#[allow(unfulfilled_lint_expectations)]` error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:41:18 + --> $DIR/expect_tool_lint_rfc_2383.rs:37:18 | -LL | #[expect(illegal_floating_point_literal_pattern)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[expect(invalid_nan_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:116:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:108:14 | LL | #[expect(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:124:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:116:14 | LL | #[expect(clippy::bytes_nth)] | ^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:130:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:122:14 | LL | #[expect(clippy::if_same_then_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:136:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:128:14 | LL | #[expect(clippy::overly_complex_bool_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs index 0901ac3640fdd..ffd694e987908 100644 --- a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs +++ b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs @@ -24,10 +24,9 @@ mod rustc_ok { pub fn rustc_lints() { let x = 42.0; - #[expect(illegal_floating_point_literal_pattern)] + #[expect(invalid_nan_comparisons)] match x { - 5.0 => {} - 6.0 => {} + f32::NAN => {} _ => {} } } @@ -40,7 +39,7 @@ mod rustc_warn { pub fn rustc_lints() { let x = 42; - #[expect(illegal_floating_point_literal_pattern)] + #[expect(invalid_nan_comparisons)] match x { 5 => {} 6 => {} diff --git a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr index efc5f349f4f44..5ae3c039d275a 100644 --- a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr +++ b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr @@ -7,19 +7,19 @@ LL | #![expect(rustdoc::missing_crate_level_docs)] = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:71:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:70:14 | LL | #[expect(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:76:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:75:14 | LL | #[expect(rustdoc::invalid_html_tags)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:81:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:80:14 | LL | #[expect(rustdoc::bare_urls)] | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/array-slice-vec/vec-matching-autoslice.rs b/tests/ui/array-slice-vec/vec-matching-autoslice.rs index 8179edf420cb0..f839cd62b1a5d 100644 --- a/tests/ui/array-slice-vec/vec-matching-autoslice.rs +++ b/tests/ui/array-slice-vec/vec-matching-autoslice.rs @@ -1,5 +1,4 @@ // run-pass -#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 pub fn main() { let x = [1, 2, 3]; diff --git a/tests/ui/binding/match-range.rs b/tests/ui/binding/match-range.rs index 1dca84dfd45ff..cb7b93e7cc65f 100644 --- a/tests/ui/binding/match-range.rs +++ b/tests/ui/binding/match-range.rs @@ -1,5 +1,4 @@ // run-pass -#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 #![feature(exclusive_range_pattern)] pub fn main() { diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs index a2a4c62fa0295..33b99259dfec9 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs @@ -1,7 +1,6 @@ // Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges. #![feature(exclusive_range_pattern)] -#![allow(illegal_floating_point_literal_pattern)] fn main() {} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr index 6b20a820b7302..1e68235303b2e 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:14:8 | LL | m!(0f32, f32::NEG_INFINITY..); | ^^^^ pattern `_` not covered @@ -11,7 +11,7 @@ LL | match $s { $($t)+ => {}, _ => todo!() } | ++++++++++++++ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8 | LL | m!(0f32, ..f32::INFINITY); | ^^^^ pattern `_` not covered @@ -23,7 +23,7 @@ LL | match $s { $($t)+ => {}, _ => todo!() } | ++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:24:8 | LL | m!('a', ..core::char::MAX); | ^^^ pattern `'\u{10ffff}'` not covered @@ -35,7 +35,7 @@ LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8 | LL | m!('a', ..ALMOST_MAX); | ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered @@ -47,7 +47,7 @@ LL | match $s { $($t)+ => {}, '\u{10fffe}'..='\u{10ffff}' => todo!() } | ++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\0'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8 | LL | m!('a', ALMOST_MIN..); | ^^^ pattern `'\0'` not covered @@ -59,7 +59,7 @@ LL | match $s { $($t)+ => {}, '\0' => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8 | LL | m!('a', ..=ALMOST_MAX); | ^^^ pattern `'\u{10ffff}'` not covered @@ -71,7 +71,7 @@ LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'b'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 | LL | m!('a', ..=VAL | VAL_2..); | ^^^ pattern `'b'` not covered @@ -83,7 +83,7 @@ LL | match $s { $($t)+ => {}, 'b' => todo!() } | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `'b'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8 | LL | m!('a', ..VAL_1 | VAL_2..); | ^^^ pattern `'b'` not covered @@ -95,7 +95,7 @@ LL | match $s { $($t)+ => {}, 'b' => todo!() } | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:39:12 | LL | m!(0, ..u8::MAX); | ^ pattern `u8::MAX` not covered @@ -107,7 +107,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `254_u8..=u8::MAX` not covered @@ -119,7 +119,7 @@ LL | match $s { $($t)+ => {}, 254_u8..=u8::MAX => todo!() } | +++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u8` not covered @@ -131,7 +131,7 @@ LL | match $s { $($t)+ => {}, 0_u8 => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u8::MAX` not covered @@ -143,7 +143,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u8` not covered @@ -155,7 +155,7 @@ LL | match $s { $($t)+ => {}, 43_u8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u8` not covered @@ -167,7 +167,7 @@ LL | match $s { $($t)+ => {}, 43_u8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:52:12 | LL | m!(0, ..u16::MAX); | ^ pattern `u16::MAX` not covered @@ -179,7 +179,7 @@ LL | match $s { $($t)+ => {}, u16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `65534_u16..=u16::MAX` not covered @@ -191,7 +191,7 @@ LL | match $s { $($t)+ => {}, 65534_u16..=u16::MAX => todo!() } | +++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u16` not covered @@ -203,7 +203,7 @@ LL | match $s { $($t)+ => {}, 0_u16 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u16::MAX` not covered @@ -215,7 +215,7 @@ LL | match $s { $($t)+ => {}, u16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u16` not covered @@ -227,7 +227,7 @@ LL | match $s { $($t)+ => {}, 43_u16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u16` not covered @@ -239,7 +239,7 @@ LL | match $s { $($t)+ => {}, 43_u16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:65:12 | LL | m!(0, ..u32::MAX); | ^ pattern `u32::MAX` not covered @@ -251,7 +251,7 @@ LL | match $s { $($t)+ => {}, u32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `4294967294_u32..=u32::MAX` not covered @@ -263,7 +263,7 @@ LL | match $s { $($t)+ => {}, 4294967294_u32..=u32::MAX => todo!() } | ++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u32` not covered @@ -275,7 +275,7 @@ LL | match $s { $($t)+ => {}, 0_u32 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u32::MAX` not covered @@ -287,7 +287,7 @@ LL | match $s { $($t)+ => {}, u32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u32` not covered @@ -299,7 +299,7 @@ LL | match $s { $($t)+ => {}, 43_u32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u32` not covered @@ -311,7 +311,7 @@ LL | match $s { $($t)+ => {}, 43_u32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:78:12 | LL | m!(0, ..u64::MAX); | ^ pattern `u64::MAX` not covered @@ -323,7 +323,7 @@ LL | match $s { $($t)+ => {}, u64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `18446744073709551614_u64..=u64::MAX` not covered @@ -335,7 +335,7 @@ LL | match $s { $($t)+ => {}, 18446744073709551614_u64..=u64::MAX => tod | ++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u64` not covered @@ -347,7 +347,7 @@ LL | match $s { $($t)+ => {}, 0_u64 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u64::MAX` not covered @@ -359,7 +359,7 @@ LL | match $s { $($t)+ => {}, u64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u64` not covered @@ -371,7 +371,7 @@ LL | match $s { $($t)+ => {}, 43_u64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u64` not covered @@ -383,7 +383,7 @@ LL | match $s { $($t)+ => {}, 43_u64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:91:12 | LL | m!(0, ..u128::MAX); | ^ pattern `u128::MAX` not covered @@ -395,7 +395,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered @@ -407,7 +407,7 @@ LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u1 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u128` not covered @@ -419,7 +419,7 @@ LL | match $s { $($t)+ => {}, 0_u128 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u128::MAX` not covered @@ -431,7 +431,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u128` not covered @@ -443,7 +443,7 @@ LL | match $s { $($t)+ => {}, 43_u128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u128` not covered @@ -455,7 +455,7 @@ LL | match $s { $($t)+ => {}, 43_u128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:107:12 | LL | m!(0, ..i8::MAX); | ^ pattern `i8::MAX` not covered @@ -467,7 +467,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `126_i8..=i8::MAX` not covered @@ -479,7 +479,7 @@ LL | match $s { $($t)+ => {}, 126_i8..=i8::MAX => todo!() } | +++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i8::MIN` not covered @@ -491,7 +491,7 @@ LL | match $s { $($t)+ => {}, i8::MIN => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i8::MAX` not covered @@ -503,7 +503,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i8` not covered @@ -515,7 +515,7 @@ LL | match $s { $($t)+ => {}, 43_i8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i8` not covered @@ -527,7 +527,7 @@ LL | match $s { $($t)+ => {}, 43_i8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:120:12 | LL | m!(0, ..i16::MAX); | ^ pattern `i16::MAX` not covered @@ -539,7 +539,7 @@ LL | match $s { $($t)+ => {}, i16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `32766_i16..=i16::MAX` not covered @@ -551,7 +551,7 @@ LL | match $s { $($t)+ => {}, 32766_i16..=i16::MAX => todo!() } | +++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i16::MIN` not covered @@ -563,7 +563,7 @@ LL | match $s { $($t)+ => {}, i16::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i16::MAX` not covered @@ -575,7 +575,7 @@ LL | match $s { $($t)+ => {}, i16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i16` not covered @@ -587,7 +587,7 @@ LL | match $s { $($t)+ => {}, 43_i16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i16` not covered @@ -599,7 +599,7 @@ LL | match $s { $($t)+ => {}, 43_i16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:133:12 | LL | m!(0, ..i32::MAX); | ^ pattern `i32::MAX` not covered @@ -611,7 +611,7 @@ LL | match $s { $($t)+ => {}, i32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `2147483646_i32..=i32::MAX` not covered @@ -623,7 +623,7 @@ LL | match $s { $($t)+ => {}, 2147483646_i32..=i32::MAX => todo!() } | ++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i32::MIN` not covered @@ -635,7 +635,7 @@ LL | match $s { $($t)+ => {}, i32::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i32::MAX` not covered @@ -647,7 +647,7 @@ LL | match $s { $($t)+ => {}, i32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i32` not covered @@ -659,7 +659,7 @@ LL | match $s { $($t)+ => {}, 43_i32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i32` not covered @@ -671,7 +671,7 @@ LL | match $s { $($t)+ => {}, 43_i32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:146:12 | LL | m!(0, ..i64::MAX); | ^ pattern `i64::MAX` not covered @@ -683,7 +683,7 @@ LL | match $s { $($t)+ => {}, i64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `9223372036854775806_i64..=i64::MAX` not covered @@ -695,7 +695,7 @@ LL | match $s { $($t)+ => {}, 9223372036854775806_i64..=i64::MAX => todo | +++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i64::MIN` not covered @@ -707,7 +707,7 @@ LL | match $s { $($t)+ => {}, i64::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i64::MAX` not covered @@ -719,7 +719,7 @@ LL | match $s { $($t)+ => {}, i64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i64` not covered @@ -731,7 +731,7 @@ LL | match $s { $($t)+ => {}, 43_i64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i64` not covered @@ -743,7 +743,7 @@ LL | match $s { $($t)+ => {}, 43_i64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:159:12 | LL | m!(0, ..i128::MAX); | ^ pattern `i128::MAX` not covered @@ -755,7 +755,7 @@ LL | match $s { $($t)+ => {}, i128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered @@ -767,7 +767,7 @@ LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i1 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i128::MIN` not covered @@ -779,7 +779,7 @@ LL | match $s { $($t)+ => {}, i128::MIN => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i128::MAX` not covered @@ -791,7 +791,7 @@ LL | match $s { $($t)+ => {}, i128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i128` not covered @@ -803,7 +803,7 @@ LL | match $s { $($t)+ => {}, 43_i128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i128` not covered diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs index 6c6ba93196b64..d5af7bea54388 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs @@ -4,7 +4,6 @@ // via `.contains(...)` and make sure the dynamic semantics match. #![feature(exclusive_range_pattern)] -#![allow(illegal_floating_point_literal_pattern)] #![allow(unreachable_patterns)] macro_rules! yes { diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs index 4b14a314e7aea..158da6509662f 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs @@ -1,5 +1,4 @@ #![feature(exclusive_range_pattern)] -#![allow(illegal_floating_point_literal_pattern)] macro_rules! m { ($s:expr, $($t:tt)+) => { diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr index e9702bb380fb3..169e776fc20fd 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr @@ -1,77 +1,77 @@ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:10:11 | LL | m!(0, ..u8::MIN); | ^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:13:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11 | LL | m!(0, ..u16::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11 | LL | m!(0, ..u32::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:16:11 | LL | m!(0, ..u64::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:19:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:18:11 | LL | m!(0, ..u128::MIN); | ^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:22:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11 | LL | m!(0, ..i8::MIN); | ^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11 | LL | m!(0, ..i16::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:26:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:25:11 | LL | m!(0, ..i32::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11 | LL | m!(0, ..i64::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:29:11 | LL | m!(0, ..i128::MIN); | ^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:14 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:32:14 | LL | m!(0f32, ..f32::NEG_INFINITY); | ^^^^^^^^^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:35:14 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:34:14 | LL | m!(0f64, ..f64::NEG_INFINITY); | ^^^^^^^^^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:38:13 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:37:13 | LL | m!('a', ..'\u{0}'); | ^^^^^^^^^ diff --git a/tests/ui/lint/issue-86600-lint-twice.rs b/tests/ui/lint/issue-86600-lint-twice.rs deleted file mode 100644 index 0e8a837d987f6..0000000000000 --- a/tests/ui/lint/issue-86600-lint-twice.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Regression test for #86600, where an instance of the -// `illegal_floating_point_literal_pattern` lint was issued twice. - -// check-pass - -fn main() { - let x = 42.0; - - match x { - 5.0 => {} - //~^ WARNING: floating-point types cannot be used in patterns - //~| WARNING: this was previously accepted by the compiler - _ => {} - } -} diff --git a/tests/ui/lint/issue-86600-lint-twice.stderr b/tests/ui/lint/issue-86600-lint-twice.stderr deleted file mode 100644 index 5a65c61212858..0000000000000 --- a/tests/ui/lint/issue-86600-lint-twice.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: floating-point types cannot be used in patterns - --> $DIR/issue-86600-lint-twice.rs:10:9 - | -LL | 5.0 => {} - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs index f80fe88cbb97e..82ca49461ed23 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs @@ -22,12 +22,8 @@ mod rustc_ok { pub fn rustc_lints() { let x = 42.0; - #[expect(illegal_floating_point_literal_pattern)] - match x { - 5.0 => {} - 6.0 => {} - _ => {} - } + #[expect(invalid_nan_comparisons)] + let _b = x == f32::NAN; } } @@ -40,13 +36,9 @@ mod rustc_warn { pub fn rustc_lints() { let x = 42; - #[expect(illegal_floating_point_literal_pattern)] + #[expect(invalid_nan_comparisons)] //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] - match x { - 5 => {} - 6 => {} - _ => {} - } + let _b = x == 5; } } diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr index 6d49e7543dc59..efe1aa04e5e29 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:37:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:33:14 | LL | #[expect(dead_code)] | ^^^^^^^^^ @@ -7,10 +7,10 @@ LL | #[expect(dead_code)] = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:43:18 + --> $DIR/expect_tool_lint_rfc_2383.rs:39:18 | -LL | #[expect(illegal_floating_point_literal_pattern)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[expect(invalid_nan_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^ warning: 2 warnings emitted diff --git a/tests/ui/match/issue-41255.rs b/tests/ui/match/issue-41255.rs deleted file mode 100644 index d163801fd1902..0000000000000 --- a/tests/ui/match/issue-41255.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Matching against float literals should result in a linter error - -#![feature(exclusive_range_pattern)] -#![allow(unused)] -#![forbid(illegal_floating_point_literal_pattern)] - -fn main() { - let x = 42.0; - match x { - 5.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - 5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - 1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - 39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - //~| WARNING hard error - - ..71.0 => {} - //~^ ERROR floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler - ..=72.0 => {} - //~^ ERROR floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler - 71.0.. => {} - //~^ ERROR floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler - _ => {}, - }; - let y = 5.0; - // Same for tuples - match (x, 5) { - (3.14, 1) => {}, //~ ERROR floating-point types cannot be used - //~| WARNING hard error - _ => {}, - } - // Or structs - struct Foo { x: f32 }; - match (Foo { x }) { - Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used - //~| WARNING hard error - _ => {}, - } -} diff --git a/tests/ui/match/issue-41255.stderr b/tests/ui/match/issue-41255.stderr deleted file mode 100644 index 9bc49654e6d4b..0000000000000 --- a/tests/ui/match/issue-41255.stderr +++ /dev/null @@ -1,115 +0,0 @@ -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:10:9 - | -LL | 5.0 => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 -note: the lint level is defined here - --> $DIR/issue-41255.rs:5:11 - | -LL | #![forbid(illegal_floating_point_literal_pattern)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:12:9 - | -LL | 5.0f32 => {}, - | ^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:14:10 - | -LL | -5.0 => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:16:9 - | -LL | 1.0 .. 33.0 => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:16:16 - | -LL | 1.0 .. 33.0 => {}, - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:20:9 - | -LL | 39.0 ..= 70.0 => {}, - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:20:18 - | -LL | 39.0 ..= 70.0 => {}, - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:25:11 - | -LL | ..71.0 => {} - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:28:12 - | -LL | ..=72.0 => {} - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:31:9 - | -LL | 71.0.. => {} - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:39:10 - | -LL | (3.14, 1) => {}, - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:46:18 - | -LL | Foo { x: 2.0 } => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: aborting due to 12 previous errors - diff --git a/tests/ui/parser/issues/issue-7222.rs b/tests/ui/parser/issues/issue-7222.rs index 6490731662664..fb18f4cd62eca 100644 --- a/tests/ui/parser/issues/issue-7222.rs +++ b/tests/ui/parser/issues/issue-7222.rs @@ -1,6 +1,5 @@ // run-pass // pretty-expanded FIXME #23616 -#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 pub fn main() { const FOO: f64 = 10.0; diff --git a/tests/ui/pattern/usefulness/floats.rs b/tests/ui/pattern/usefulness/floats.rs index 2616dfadb85e8..63ce26adab2a4 100644 --- a/tests/ui/pattern/usefulness/floats.rs +++ b/tests/ui/pattern/usefulness/floats.rs @@ -1,5 +1,4 @@ #![feature(exclusive_range_pattern)] -#![allow(illegal_floating_point_literal_pattern)] #![deny(unreachable_patterns)] fn main() { diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr index f50419118246b..d99f05f52842d 100644 --- a/tests/ui/pattern/usefulness/floats.stderr +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/floats.rs:11:11 + --> $DIR/floats.rs:10:11 | LL | match 0.0 { | ^^^ pattern `_` not covered @@ -12,49 +12,49 @@ LL + _ => todo!() | error: unreachable pattern - --> $DIR/floats.rs:19:9 + --> $DIR/floats.rs:18:9 | LL | 0.01f64 => {} | ^^^^^^^ | note: the lint level is defined here - --> $DIR/floats.rs:3:9 + --> $DIR/floats.rs:2:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:20:9 + --> $DIR/floats.rs:19:9 | LL | 0.02f64 => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:21:9 + --> $DIR/floats.rs:20:9 | LL | 6.5f64 => {} | ^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:23:9 + --> $DIR/floats.rs:22:9 | LL | 1.0f64..=4.0f64 => {} | ^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:35:9 + --> $DIR/floats.rs:34:9 | LL | 0.01f32 => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:36:9 + --> $DIR/floats.rs:35:9 | LL | 0.02f32 => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:37:9 + --> $DIR/floats.rs:36:9 | LL | 6.5f32 => {} | ^^^^^^ diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.rs b/tests/ui/pattern/usefulness/non-exhaustive-match.rs index 1cb58b8cebef7..44acd397f8d58 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match.rs +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.rs @@ -1,5 +1,3 @@ -#![allow(illegal_floating_point_literal_pattern)] - enum T { A, B } fn main() { diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr index 4bebd3cbbefd0..61ed0eb4fc4e2 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -1,11 +1,11 @@ error[E0004]: non-exhaustive patterns: `T::A` not covered - --> $DIR/non-exhaustive-match.rs:7:11 + --> $DIR/non-exhaustive-match.rs:5:11 | LL | match x { T::B => { } } | ^ pattern `T::A` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match.rs:3:6 + --> $DIR/non-exhaustive-match.rs:1:6 | LL | enum T { A, B } | ^ - not covered @@ -16,7 +16,7 @@ LL | match x { T::B => { }, T::A => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `false` not covered - --> $DIR/non-exhaustive-match.rs:8:11 + --> $DIR/non-exhaustive-match.rs:6:11 | LL | match true { | ^^^^ pattern `false` not covered @@ -29,7 +29,7 @@ LL + false => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/non-exhaustive-match.rs:11:11 + --> $DIR/non-exhaustive-match.rs:9:11 | LL | match Some(10) { | ^^^^^^^^ pattern `Some(_)` not covered @@ -47,7 +47,7 @@ LL + Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered - --> $DIR/non-exhaustive-match.rs:14:11 + --> $DIR/non-exhaustive-match.rs:12:11 | LL | match (2, 3, 4) { | ^^^^^^^^^ patterns `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered @@ -60,7 +60,7 @@ LL + (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!() | error[E0004]: non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered - --> $DIR/non-exhaustive-match.rs:18:11 + --> $DIR/non-exhaustive-match.rs:16:11 | LL | match (T::A, T::A) { | ^^^^^^^^^^^^ patterns `(T::A, T::A)` and `(T::B, T::B)` not covered @@ -73,13 +73,13 @@ LL + (T::A, T::A) | (T::B, T::B) => todo!() | error[E0004]: non-exhaustive patterns: `T::B` not covered - --> $DIR/non-exhaustive-match.rs:22:11 + --> $DIR/non-exhaustive-match.rs:20:11 | LL | match T::A { | ^^^^ pattern `T::B` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match.rs:3:6 + --> $DIR/non-exhaustive-match.rs:1:6 | LL | enum T { A, B } | ^ - not covered @@ -91,7 +91,7 @@ LL + T::B => todo!() | error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/non-exhaustive-match.rs:33:11 + --> $DIR/non-exhaustive-match.rs:31:11 | LL | match *vec { | ^^^^ pattern `[]` not covered @@ -104,7 +104,7 @@ LL + [] => todo!() | error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered - --> $DIR/non-exhaustive-match.rs:46:11 + --> $DIR/non-exhaustive-match.rs:44:11 | LL | match *vec { | ^^^^ pattern `[_, _, _, _, ..]` not covered diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs index c5bca8c970dae..c8808c7eea9e2 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs @@ -1,7 +1,6 @@ // Matching against NaN should result in an error #![feature(exclusive_range_pattern)] #![allow(unused)] -#![allow(illegal_floating_point_literal_pattern)] const NAN: f64 = f64::NAN; diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr index deda07150c52d..bfcf919fbe8fc 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr @@ -1,5 +1,5 @@ error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:11:9 + --> $DIR/issue-6804-nan-match.rs:10:9 | LL | NAN => {}, | ^^^ @@ -8,7 +8,7 @@ LL | NAN => {}, = help: try using the `is_nan` method instead error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:16:10 + --> $DIR/issue-6804-nan-match.rs:15:10 | LL | [NAN, _] => {}, | ^^^ @@ -17,7 +17,7 @@ LL | [NAN, _] => {}, = help: try using the `is_nan` method instead error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:22:9 + --> $DIR/issue-6804-nan-match.rs:21:9 | LL | NAN..=1.0 => {}, | ^^^ @@ -26,13 +26,13 @@ LL | NAN..=1.0 => {}, = help: try using the `is_nan` method instead error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/issue-6804-nan-match.rs:22:9 + --> $DIR/issue-6804-nan-match.rs:21:9 | LL | NAN..=1.0 => {}, | ^^^^^^^^^ lower bound larger than upper bound error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:24:16 + --> $DIR/issue-6804-nan-match.rs:23:16 | LL | -1.0..=NAN => {}, | ^^^ @@ -41,13 +41,13 @@ LL | -1.0..=NAN => {}, = help: try using the `is_nan` method instead error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/issue-6804-nan-match.rs:24:9 + --> $DIR/issue-6804-nan-match.rs:23:9 | LL | -1.0..=NAN => {}, | ^^^^^^^^^^ lower bound larger than upper bound error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:26:9 + --> $DIR/issue-6804-nan-match.rs:25:9 | LL | NAN.. => {}, | ^^^ @@ -56,13 +56,13 @@ LL | NAN.. => {}, = help: try using the `is_nan` method instead error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/issue-6804-nan-match.rs:26:9 + --> $DIR/issue-6804-nan-match.rs:25:9 | LL | NAN.. => {}, | ^^^^^ lower bound larger than upper bound error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:28:11 + --> $DIR/issue-6804-nan-match.rs:27:11 | LL | ..NAN => {}, | ^^^ @@ -71,7 +71,7 @@ LL | ..NAN => {}, = help: try using the `is_nan` method instead error[E0579]: lower range bound must be less than upper - --> $DIR/issue-6804-nan-match.rs:28:9 + --> $DIR/issue-6804-nan-match.rs:27:9 | LL | ..NAN => {}, | ^^^^^ diff --git a/tests/ui/union/union-pat-refutability.rs b/tests/ui/union/union-pat-refutability.rs index 17ac6c6dfa9bf..edcc1add38fde 100644 --- a/tests/ui/union/union-pat-refutability.rs +++ b/tests/ui/union/union-pat-refutability.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] -#![allow(illegal_floating_point_literal_pattern)] #[repr(u32)] enum Tag { From 9f14fc4af4554b5ae8b727ae68460777051f1f74 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 23 Sep 2023 23:02:42 +0200 Subject: [PATCH 259/676] add test checking behavior of matching on floats, and NaNs in consts --- tests/ui/match/match-float.rs | 11 +++++++ .../issue-6804-nan-match.rs | 10 ++++++ .../issue-6804-nan-match.stderr | 31 ++++++++++++------- 3 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 tests/ui/match/match-float.rs diff --git a/tests/ui/match/match-float.rs b/tests/ui/match/match-float.rs new file mode 100644 index 0000000000000..8da6a9ed2049c --- /dev/null +++ b/tests/ui/match/match-float.rs @@ -0,0 +1,11 @@ +// run-pass +// Makes sure we use `==` (not bitwise) semantics for float comparison. + +fn main() { + const F1: f32 = 0.0; + const F2: f32 = -0.0; + assert_eq!(F1, F2); + assert_ne!(F1.to_bits(), F2.to_bits()); + assert!(matches!(F1, F2)); + assert!(matches!(F2, F1)); +} diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs index c8808c7eea9e2..d43db576b3848 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs @@ -4,6 +4,11 @@ const NAN: f64 = f64::NAN; +#[derive(PartialEq, Eq)] +struct MyType(T); + +const C: MyType = MyType(f32::NAN); + fn main() { let x = NAN; match x { @@ -16,6 +21,11 @@ fn main() { _ => {}, }; + match MyType(1.0f32) { + C => {}, //~ ERROR cannot use NaN in patterns + _ => {}, + } + // Also cover range patterns match x { NAN..=1.0 => {}, //~ ERROR cannot use NaN in patterns diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr index bfcf919fbe8fc..167ada783c24c 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr @@ -1,5 +1,5 @@ error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:10:9 + --> $DIR/issue-6804-nan-match.rs:15:9 | LL | NAN => {}, | ^^^ @@ -8,7 +8,7 @@ LL | NAN => {}, = help: try using the `is_nan` method instead error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:15:10 + --> $DIR/issue-6804-nan-match.rs:20:10 | LL | [NAN, _] => {}, | ^^^ @@ -17,7 +17,16 @@ LL | [NAN, _] => {}, = help: try using the `is_nan` method instead error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:21:9 + --> $DIR/issue-6804-nan-match.rs:25:9 + | +LL | C => {}, + | ^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:31:9 | LL | NAN..=1.0 => {}, | ^^^ @@ -26,13 +35,13 @@ LL | NAN..=1.0 => {}, = help: try using the `is_nan` method instead error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/issue-6804-nan-match.rs:21:9 + --> $DIR/issue-6804-nan-match.rs:31:9 | LL | NAN..=1.0 => {}, | ^^^^^^^^^ lower bound larger than upper bound error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:23:16 + --> $DIR/issue-6804-nan-match.rs:33:16 | LL | -1.0..=NAN => {}, | ^^^ @@ -41,13 +50,13 @@ LL | -1.0..=NAN => {}, = help: try using the `is_nan` method instead error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/issue-6804-nan-match.rs:23:9 + --> $DIR/issue-6804-nan-match.rs:33:9 | LL | -1.0..=NAN => {}, | ^^^^^^^^^^ lower bound larger than upper bound error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:25:9 + --> $DIR/issue-6804-nan-match.rs:35:9 | LL | NAN.. => {}, | ^^^ @@ -56,13 +65,13 @@ LL | NAN.. => {}, = help: try using the `is_nan` method instead error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/issue-6804-nan-match.rs:25:9 + --> $DIR/issue-6804-nan-match.rs:35:9 | LL | NAN.. => {}, | ^^^^^ lower bound larger than upper bound error: cannot use NaN in patterns - --> $DIR/issue-6804-nan-match.rs:27:11 + --> $DIR/issue-6804-nan-match.rs:37:11 | LL | ..NAN => {}, | ^^^ @@ -71,12 +80,12 @@ LL | ..NAN => {}, = help: try using the `is_nan` method instead error[E0579]: lower range bound must be less than upper - --> $DIR/issue-6804-nan-match.rs:27:9 + --> $DIR/issue-6804-nan-match.rs:37:9 | LL | ..NAN => {}, | ^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors Some errors have detailed explanations: E0030, E0579. For more information about an error, try `rustc --explain E0030`. From 90254cd55fcdc3fc7101300398b6e715d99b9c3e Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 26 Jan 2024 19:45:00 +0300 Subject: [PATCH 260/676] ScopeTree: remove destruction_scopes as unused last usages removed by https://github.com/rust-lang/rust/pull/116170 --- compiler/rustc_middle/src/middle/region.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 5d6a7f75df843..b9914f6cb7a00 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -221,9 +221,6 @@ pub struct ScopeTree { /// variable is declared. var_map: FxIndexMap, - /// Maps from a `NodeId` to the associated destruction scope (if any). - destruction_scopes: FxIndexMap, - /// Identifies expressions which, if captured into a temporary, ought to /// have a temporary whose lifetime extends to the end of the enclosing *block*, /// and not the enclosing *statement*. Expressions that are not present in this @@ -336,11 +333,6 @@ impl ScopeTree { let prev = self.parent_map.insert(child, p); assert!(prev.is_none()); } - - // Record the destruction scopes for later so we can query them. - if let ScopeData::Destruction = child.data { - self.destruction_scopes.insert(child.item_local_id(), child); - } } pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) { From bdfb9172c187e5f3527c3a4aba3741badc279515 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 26 Jan 2024 17:54:41 +0100 Subject: [PATCH 261/676] interpret/memory: fix safety comment for large array memset optimization --- compiler/rustc_const_eval/src/interpret/memory.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 3afd14eb57435..38ad8cbf3a691 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -396,7 +396,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// to the allocation it points to. Supports both shared and mutable references, as the actual /// checking is offloaded to a helper closure. /// - /// If this returns `None`, the size is 0; it can however return `Some` even for size 0. + /// Returns `None` if and only if the size is 0. fn check_and_deref_ptr( &self, ptr: Pointer>, @@ -1214,10 +1214,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let size_in_bytes = size.bytes_usize(); // For particularly large arrays (where this is perf-sensitive) it's common that // we're writing a single byte repeatedly. So, optimize that case to a memset. - if size_in_bytes == 1 && num_copies >= 1 { - // SAFETY: `src_bytes` would be read from anyway by copies below (num_copies >= 1). - // Since size_in_bytes = 1, then the `init.no_bytes_init()` check above guarantees - // that this read at type `u8` is OK -- it must be an initialized byte. + if size_in_bytes == 1 { + debug_assert!(num_copies >= 1); // we already handled the zero-sized cases above. + // SAFETY: `src_bytes` would be read from anyway by `copy` below (num_copies >= 1). let value = *src_bytes; dest_bytes.write_bytes(value, (size * num_copies).bytes_usize()); } else if src_alloc_id == dest_alloc_id { From f941247bddff8343cc813b46ec219873e0e33807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 26 Jan 2024 18:26:36 +0100 Subject: [PATCH 262/676] Add fmease to the compiler review rotation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index a9ddd1b99c72a..ab2fe033e7294 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -650,6 +650,7 @@ compiler-team-contributors = [ "@TaKO8Ki", "@b-naber", "@nnethercote", + "@fmease", ] compiler = [ "compiler-team", From 3f3a153056b0d60305f5b7d676ab2d720a91fef9 Mon Sep 17 00:00:00 2001 From: wackbyte Date: Fri, 26 Jan 2024 11:09:27 -0500 Subject: [PATCH 263/676] Use `` for array/slice equality `impl`s Makes the trait implementation documentation for arrays and slices appear more consistent. --- library/core/src/array/equality.rs | 64 ++++++++++----------- library/core/src/slice/cmp.rs | 8 +-- tests/ui/consts/too_generic_eval_ice.stderr | 12 ++-- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index d749865f76f51..bdb6599abf549 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -2,36 +2,36 @@ use crate::cmp::BytewiseEq; use crate::convert::TryInto; #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[B; N]> for [A; N] +impl PartialEq<[U; N]> for [T; N] where - A: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &[B; N]) -> bool { + fn eq(&self, other: &[U; N]) -> bool { SpecArrayEq::spec_eq(self, other) } #[inline] - fn ne(&self, other: &[B; N]) -> bool { + fn ne(&self, other: &[U; N]) -> bool { SpecArrayEq::spec_ne(self, other) } } #[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 { - let b: Result<&[B; N], _> = other.try_into(); + fn eq(&self, other: &[U]) -> bool { + let b: Result<&[U; N], _> = other.try_into(); match b { Ok(b) => *self == *b, Err(_) => false, } } #[inline] - fn ne(&self, other: &[B]) -> bool { - let b: Result<&[B; N], _> = other.try_into(); + fn ne(&self, other: &[U]) -> bool { + let b: Result<&[U; N], _> = other.try_into(); match b { Ok(b) => *self != *b, Err(_) => true, @@ -40,21 +40,21 @@ where } #[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 { - 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 f78617994aa921869858ec78ceb70b5d5078ada5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 26 Jan 2024 18:08:00 +0000 Subject: [PATCH 264/676] Update rand test This contains a fix for a recently introduced warning. --- build_system/tests.rs | 4 ++-- patches/0001-rand-Allow-warnings.patch | 24 ------------------------ patches/rand-lock.toml | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 26 deletions(-) delete mode 100644 patches/0001-rand-Allow-warnings.patch diff --git a/build_system/tests.rs b/build_system/tests.rs index 20f6d70a58bf6..818f3d6f08d26 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -113,8 +113,8 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ pub(crate) static RAND_REPO: GitRepo = GitRepo::github( "rust-random", "rand", - "9a02c819cc1e4ec6959ae25eafbb5cf6acb68234", - "4934f0afb1d1c2ca", + "1f4507a8e1cf8050e4ceef95eeda8f64645b6719", + "981f8bf489338978", "rand", ); diff --git a/patches/0001-rand-Allow-warnings.patch b/patches/0001-rand-Allow-warnings.patch deleted file mode 100644 index ae46e957efa04..0000000000000 --- a/patches/0001-rand-Allow-warnings.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 8330c138c91f71ad43b38c026ee14b154f34a1b8 Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Sun, 21 Jan 2024 11:12:19 +0000 -Subject: [PATCH] Allow warnings - ---- - rand_core/src/lib.rs | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs -index a5a7fb1..6c84068 100644 ---- a/rand_core/src/lib.rs -+++ b/rand_core/src/lib.rs -@@ -34,7 +34,6 @@ - )] - #![deny(missing_docs)] - #![deny(missing_debug_implementations)] --#![doc(test(attr(allow(unused_variables), deny(warnings))))] - #![cfg_attr(doc_cfg, feature(doc_cfg))] - #![no_std] - --- -2.34.1 - diff --git a/patches/rand-lock.toml b/patches/rand-lock.toml index aacf3653c169e..815b828a68bd6 100644 --- a/patches/rand-lock.toml +++ b/patches/rand-lock.toml @@ -487,6 +487,7 @@ dependencies = [ "rand_pcg", "rayon", "serde", + "zerocopy", ] [[package]] @@ -505,6 +506,7 @@ version = "0.7.0" dependencies = [ "getrandom", "serde", + "zerocopy", ] [[package]] @@ -525,6 +527,7 @@ name = "rand_pcg" version = "0.4.0" dependencies = [ "bincode", + "rand", "rand_core", "serde", ] @@ -823,3 +826,23 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "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 2.0.37", +] From 3e50cf65025f96854d6597e80449b0d64ad89589 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 26 Jan 2024 18:24:04 +0000 Subject: [PATCH 265/676] Rustup to rustc 1.77.0-nightly (5bd5d214e 2024-01-25) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 5fdaa2a931082..ccd7edbc2a917 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-01-21" +channel = "nightly-2024-01-26" components = ["rust-src", "rustc-dev", "llvm-tools"] From e320004dade39b99cd1f239c5d1289ea2ebf2c79 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 24 Jan 2024 22:32:46 +0100 Subject: [PATCH 266/676] 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 267/676] 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 268/676] 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 269/676] 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 866364cc5d79b26ec1ab58eca0cc4c3416b5a1bc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 23 Jan 2024 19:09:12 +0000 Subject: [PATCH 270/676] Normalize field types before checking validity --- .../src/transform/validate.rs | 23 ++++++++------ .../struct-assignment-validity.rs | 31 +++++++++++++++++++ 2 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/struct-assignment-validity.rs diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 5564902396eda..21bdb66a27631 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -810,13 +810,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let adt_def = self.tcx.adt_def(def_id); assert!(adt_def.is_union()); assert_eq!(idx, FIRST_VARIANT); - let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args); - if fields.len() != 1 { + let dest_ty = self.tcx.normalize_erasing_regions( + self.param_env, + adt_def.non_enum_variant().fields[field].ty(self.tcx, args), + ); + if fields.len() == 1 { + let src_ty = fields.raw[0].ty(self.body, self.tcx); + if !self.mir_assign_valid_types(src_ty, dest_ty) { + self.fail(location, "union field has the wrong type"); + } + } else { self.fail(location, "unions should have one initialized field"); } - if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) { - self.fail(location, "union field has the wrong type"); - } } AggregateKind::Adt(def_id, idx, args, _, None) => { let adt_def = self.tcx.adt_def(def_id); @@ -826,10 +831,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.fail(location, "adt has the wrong number of initialized fields"); } for (src, dest) in std::iter::zip(fields, &variant.fields) { - if !self.mir_assign_valid_types( - src.ty(self.body, self.tcx), - dest.ty(self.tcx, args), - ) { + let dest_ty = self + .tcx + .normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args)); + if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) { self.fail(location, "adt field has the wrong type"); } } diff --git a/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs b/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs new file mode 100644 index 0000000000000..39f0b9a02eeae --- /dev/null +++ b/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs @@ -0,0 +1,31 @@ +// compile-flags: -Zvalidate-mir +// check-pass + +// Check that we don't cause cycle errors when validating pre-`Reveal::All` MIR +// that assigns opaques through normalized projections. + +#![feature(impl_trait_in_assoc_type)] + +struct Bar; + +trait Trait { + type Assoc; + fn foo() -> Foo; +} + +impl Trait for Bar { + type Assoc = impl std::fmt::Debug; + fn foo() -> Foo + where + Self::Assoc:, + { + let x: ::Assoc = (); + Foo { field: () } + } +} + +struct Foo { + field: ::Assoc, +} + +fn main() {} From 6cf7b5f8d7e488ff6b14f8ed552b470ee5ec9cbf Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 26 Jan 2024 19:45:46 +0100 Subject: [PATCH 271/676] 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 304361a10c2a1c550e47f89efc55901ff3b4cf2a Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 26 Jan 2024 20:32:55 +0100 Subject: [PATCH 272/676] Improve handling of numbers in IntoDiagnosticArg --- compiler/rustc_errors/src/diagnostic_impls.rs | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index f6679ae9bb352..d18be69900c82 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -58,16 +58,29 @@ macro_rules! into_diagnostic_arg_using_display { } } +macro_rules! into_diagnostic_arg_for_number { + ($( $ty:ty ),+ $(,)?) => { + $( + impl IntoDiagnosticArg for $ty { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + // HACK: `FluentNumber` the underline backing struct represent + // numbers using a f64 which can 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 { + DiagnosticArgValue::Number(n) + } else { + self.to_string().into_diagnostic_arg() + } + } + } + )+ + } +} + into_diagnostic_arg_using_display!( ast::ParamKindOrd, - i8, - u8, - i16, - u16, - u32, - i64, - i128, - u128, std::io::Error, Box, std::num::NonZeroU32, @@ -82,17 +95,7 @@ into_diagnostic_arg_using_display!( ExitStatus, ); -impl IntoDiagnosticArg for i32 { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Number(self.into()) - } -} - -impl IntoDiagnosticArg for u64 { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Number(self.into()) - } -} +into_diagnostic_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); impl IntoDiagnosticArg for bool { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { @@ -154,12 +157,6 @@ impl IntoDiagnosticArg for PathBuf { } } -impl IntoDiagnosticArg for usize { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Number(self as i128) - } -} - impl IntoDiagnosticArg for PanicStrategy { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string())) From 93ff4a4f4806965a0ea19a0441e2e9ec8e2404f9 Mon Sep 17 00:00:00 2001 From: Urgau <3616612+Urgau@users.noreply.github.com> Date: Fri, 26 Jan 2024 21:01:45 +0100 Subject: [PATCH 273/676] Fix typo Co-authored-by: Michael Goulet --- compiler/rustc_errors/src/diagnostic_impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index d18be69900c82..d58d05095cdcb 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -64,7 +64,7 @@ macro_rules! into_diagnostic_arg_for_number { impl IntoDiagnosticArg for $ty { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { // HACK: `FluentNumber` the underline backing struct represent - // numbers using a f64 which can represent all the i128 numbers + // 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. From 169c72861fc932cea1ce832ae932ad3effe91f12 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Fri, 26 Jan 2024 12:31:46 -0800 Subject: [PATCH 274/676] Remove myself from review rotation --- triagebot.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 264f6efd982c7..3b4e01f4a0fd7 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -662,7 +662,6 @@ libs = [ "@joshtriplett", "@Mark-Simulacrum", "@m-ou-se", - "@thomcc", ] bootstrap = [ "@Mark-Simulacrum", @@ -802,7 +801,7 @@ project-stable-mir = [ "/library/panic_unwind" = ["libs"] "/library/proc_macro" = ["@petrochenkov"] "/library/std" = ["libs"] -"/library/std/src/sys/pal/windows" = ["@ChrisDenton", "@thomcc"] +"/library/std/src/sys/pal/windows" = ["@ChrisDenton"] "/library/stdarch" = ["libs"] "/library/test" = ["libs"] "/src/bootstrap" = ["bootstrap"] From 3691ab8e7adc91f877ded39faba826f5c9f8a5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 26 Jan 2024 20:07:37 +0000 Subject: [PATCH 275/676] Use only one label for multiple unsatisfied bounds on type (astconv) --- .../rustc_hir_analysis/src/astconv/errors.rs | 39 +++++++++++++------ ...nsatisfied-bounds-in-multiple-impls.stderr | 5 +-- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index bfe88df4e1a55..b2d5d3885d938 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -461,22 +461,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return err.emit(); } - let mut bound_spans = Vec::new(); + let mut bound_spans: FxHashMap> = Default::default(); let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { - let msg = format!( - "doesn't satisfy `{}`", - if obligation.len() > 50 { quiet } else { obligation } - ); + let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); match &self_ty.kind() { // Point at the type that couldn't satisfy the bound. - ty::Adt(def, _) => bound_spans.push((tcx.def_span(def.did()), msg)), + ty::Adt(def, _) => { + bound_spans.entry(tcx.def_span(def.did())).or_default().push(msg) + } // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _, _) => { for pred in preds.iter() { match pred.skip_binder() { ty::ExistentialPredicate::Trait(tr) => { - bound_spans.push((tcx.def_span(tr.def_id), msg.clone())) + bound_spans + .entry(tcx.def_span(tr.def_id)) + .or_default() + .push(msg.clone()); } ty::ExistentialPredicate::Projection(_) | ty::ExistentialPredicate::AutoTrait(_) => {} @@ -485,7 +487,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Point at the closure that couldn't satisfy the bound. ty::Closure(def_id, _) => { - bound_spans.push((tcx.def_span(*def_id), format!("doesn't satisfy `{quiet}`"))) + bound_spans + .entry(tcx.def_span(*def_id)) + .or_default() + .push(format!("`{quiet}`")); } _ => {} } @@ -554,12 +559,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds") ); - bound_spans.sort(); - bound_spans.dedup(); - for (span, msg) in bound_spans { + let mut bound_spans: Vec<(Span, Vec)> = bound_spans + .into_iter() + .map(|(span, mut bounds)| { + bounds.sort(); + bounds.dedup(); + (span, bounds) + }) + .collect(); + bound_spans.sort_by_key(|(span, _)| *span); + for (span, bounds) in bound_spans { if !tcx.sess.source_map().is_span_accessible(span) { continue; } + let msg = match &bounds[..] { + [bound] => format!("doesn't satisfy {bound}"), + [bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")), + [] => unreachable!(), + }; err.span_label(span, msg); } add_def_label(&mut err); diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr index 650b5946064c2..1613af6b8b152 100644 --- a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr +++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr @@ -4,10 +4,7 @@ error: the associated type `X` exists for `S`, but its LL | struct S(A, B); | -------------- associated item `X` not found for this struct LL | struct Featureless; - | ------------------ - | | - | doesn't satisfy `Featureless: One` - | doesn't satisfy `Featureless: Two` + | ------------------ doesn't satisfy `Featureless: One` or `Featureless: Two` ... LL | let _: S::::X; | ^ associated type cannot be referenced on `S` due to unsatisfied trait bounds From 757b726f8689c508dbd3979ea6b547a74d6481b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 26 Jan 2024 20:34:29 +0000 Subject: [PATCH 276/676] Use only one label for multiple unsatisfied bounds on type (typeck) --- .../rustc_hir_typeck/src/method/suggest.rs | 48 ++++++++++++++----- .../box/unit/unique-object-noncopyable.stderr | 15 ++---- tests/ui/box/unit/unique-pinned-nocopy.stderr | 12 ++--- .../deriving-with-repr-packed-2.stderr | 5 +- tests/ui/derives/issue-91550.stderr | 25 ++-------- ...gat-bound-during-assoc-ty-selection.stderr | 3 -- ...method-unsatisfied-assoc-type-predicate.rs | 3 +- ...od-unsatisfied-assoc-type-predicate.stderr | 5 +- .../ui/iterators/vec-on-unimplemented.stderr | 3 -- .../ui/mismatched_types/issue-36053-2.stderr | 6 +-- .../derive-trait-for-method-call.stderr | 16 +------ .../mut-borrow-needed-by-trait.stderr | 3 -- .../ui/suggestions/suggest-change-mut.stderr | 3 -- tests/ui/traits/track-obligations.stderr | 5 +- tests/ui/typeck/derive-sugg-arg-arity.stderr | 3 +- tests/ui/typeck/issue-31173.stderr | 6 --- 16 files changed, 56 insertions(+), 105 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 0b8a25eedafad..d7a0565895d3e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -9,7 +9,7 @@ use crate::Expectation; use crate::FnCtxt; use rustc_ast::ast::Mutability; use rustc_attr::parse_confusables; -use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::StashKey; use rustc_errors::{ @@ -547,7 +547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - let mut bound_spans = vec![]; + let mut bound_spans: FxHashMap> = Default::default(); let mut restrict_type_params = false; let mut unsatisfied_bounds = false; if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { @@ -642,19 +642,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false }; let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { - let msg = format!( - "doesn't satisfy `{}`", - if obligation.len() > 50 { quiet } else { obligation } - ); + let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); match &self_ty.kind() { // Point at the type that couldn't satisfy the bound. - ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)), + ty::Adt(def, _) => { + bound_spans.entry(tcx.def_span(def.did())).or_default().push(msg) + } // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _, _) => { for pred in preds.iter() { match pred.skip_binder() { ty::ExistentialPredicate::Trait(tr) => { - bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone())) + bound_spans + .entry(tcx.def_span(tr.def_id)) + .or_default() + .push(msg.clone()); } ty::ExistentialPredicate::Projection(_) | ty::ExistentialPredicate::AutoTrait(_) => {} @@ -662,8 +664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } // Point at the closure that couldn't satisfy the bound. - ty::Closure(def_id, _) => bound_spans - .push((tcx.def_span(*def_id), format!("doesn't satisfy `{quiet}`"))), + ty::Closure(def_id, _) => { + bound_spans + .entry(tcx.def_span(*def_id)) + .or_default() + .push(format!("`{quiet}`")); + } _ => {} } }; @@ -1170,9 +1176,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name); - bound_spans.sort(); - bound_spans.dedup(); - for (span, msg) in bound_spans.into_iter() { + #[allow(rustc::potential_query_instability)] // We immediately sort the resulting Vec. + let mut bound_spans: Vec<(Span, Vec)> = bound_spans + .into_iter() + .map(|(span, mut bounds)| { + bounds.sort(); + bounds.dedup(); + (span, bounds) + }) + .collect(); + bound_spans.sort_by_key(|(span, _)| *span); + for (span, bounds) in bound_spans { + if !tcx.sess.source_map().is_span_accessible(span) { + continue; + } + let msg = match &bounds[..] { + [bound] => format!("doesn't satisfy {bound}"), + [bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")), + [] => unreachable!(), + }; err.span_label(span, msg); } diff --git a/tests/ui/box/unit/unique-object-noncopyable.stderr b/tests/ui/box/unit/unique-object-noncopyable.stderr index 1b98d09ccddb0..49547872d1a7b 100644 --- a/tests/ui/box/unit/unique-object-noncopyable.stderr +++ b/tests/ui/box/unit/unique-object-noncopyable.stderr @@ -1,18 +1,11 @@ error[E0599]: the method `clone` exists for struct `Box`, but its trait bounds were not satisfied --> $DIR/unique-object-noncopyable.rs:24:16 | -LL | trait Foo { - | --------- - | | - | doesn't satisfy `dyn Foo: Clone` - | doesn't satisfy `dyn Foo: Sized` +LL | trait Foo { + | --------- doesn't satisfy `dyn Foo: Clone` or `dyn Foo: Sized` ... -LL | let _z = y.clone(); - | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL - ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL - | - = note: doesn't satisfy `Box: Clone` +LL | let _z = y.clone(); + | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `dyn Foo: Sized` diff --git a/tests/ui/box/unit/unique-pinned-nocopy.stderr b/tests/ui/box/unit/unique-pinned-nocopy.stderr index d662a2d6d0512..d2bf72249c451 100644 --- a/tests/ui/box/unit/unique-pinned-nocopy.stderr +++ b/tests/ui/box/unit/unique-pinned-nocopy.stderr @@ -1,15 +1,11 @@ error[E0599]: the method `clone` exists for struct `Box`, but its trait bounds were not satisfied --> $DIR/unique-pinned-nocopy.rs:12:16 | -LL | struct R { - | -------- doesn't satisfy `R: Clone` +LL | struct R { + | -------- doesn't satisfy `R: Clone` ... -LL | let _j = i.clone(); - | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL - ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL - | - = note: doesn't satisfy `Box: Clone` +LL | let _j = i.clone(); + | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `R: Clone` diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index 0eaca7e236098..172dd80fe1d09 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -8,10 +8,7 @@ LL | pub struct Foo(T, T, T); | doesn't satisfy `Foo: Clone` LL | LL | struct NonCopy; - | -------------- - | | - | doesn't satisfy `NonCopy: Clone` - | doesn't satisfy `NonCopy: Copy` + | -------------- doesn't satisfy `NonCopy: Clone` or `NonCopy: Copy` ... LL | _ = x.clone(); | ^^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index 1324b80b5fcdb..9e17189671827 100644 --- a/tests/ui/derives/issue-91550.stderr +++ b/tests/ui/derives/issue-91550.stderr @@ -2,11 +2,7 @@ error[E0599]: the method `insert` exists for struct `HashSet`, but its tr --> $DIR/issue-91550.rs:8:8 | LL | struct Value(u32); - | ------------ - | | - | doesn't satisfy `Value: Eq` - | doesn't satisfy `Value: Hash` - | doesn't satisfy `Value: PartialEq` + | ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq` ... LL | hs.insert(Value(0)); | ^^^^^^ @@ -26,10 +22,7 @@ error[E0599]: the method `use_eq` exists for struct `Object`, but its --> $DIR/issue-91550.rs:26:9 | LL | pub struct NoDerives; - | -------------------- - | | - | doesn't satisfy `NoDerives: Eq` - | doesn't satisfy `NoDerives: PartialEq` + | -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq` LL | LL | struct Object(T); | ---------------- method `use_eq` not found for this struct @@ -57,12 +50,7 @@ error[E0599]: the method `use_ord` exists for struct `Object`, but it --> $DIR/issue-91550.rs:27:9 | LL | pub struct NoDerives; - | -------------------- - | | - | doesn't satisfy `NoDerives: Eq` - | doesn't satisfy `NoDerives: Ord` - | doesn't satisfy `NoDerives: PartialEq` - | doesn't satisfy `NoDerives: PartialOrd` + | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd` LL | LL | struct Object(T); | ---------------- method `use_ord` not found for this struct @@ -94,12 +82,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object $DIR/issue-91550.rs:28:9 | LL | pub struct NoDerives; - | -------------------- - | | - | doesn't satisfy `NoDerives: Eq` - | doesn't satisfy `NoDerives: Ord` - | doesn't satisfy `NoDerives: PartialEq` - | doesn't satisfy `NoDerives: PartialOrd` + | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd` LL | LL | struct Object(T); | ---------------- method `use_ord_and_partial_ord` not found for this struct diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr index 3a973d356dc98..2ce10ce9c1cc0 100644 --- a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr @@ -26,9 +26,6 @@ LL | enum Node { ... LL | let mut list = RcNode::::new(); | ^^^ doesn't have a size known at compile-time - --> $SRC_DIR/core/src/ops/deref.rs:LL:COL - | - = note: doesn't satisfy `_: Sized` | note: trait bound `Node: Sized` was not satisfied --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:18 diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs index 83655341d6a24..1f9e4f24b161c 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs @@ -17,8 +17,7 @@ impl = i32>> M for T {} struct S; //~^ NOTE method `f` not found for this -//~| NOTE doesn't satisfy `::Y = i32` -//~| NOTE doesn't satisfy `S: M` +//~| NOTE doesn't satisfy `::Y = i32` or `S: M` impl X for S { type Y = bool; diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr index 7ca0b2912a68a..489b2772ad8c3 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr @@ -1,12 +1,11 @@ error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied - --> $DIR/method-unsatisfied-assoc-type-predicate.rs:28:7 + --> $DIR/method-unsatisfied-assoc-type-predicate.rs:27:7 | LL | struct S; | -------- | | | method `f` not found for this struct - | doesn't satisfy `::Y = i32` - | doesn't satisfy `S: M` + | doesn't satisfy `::Y = i32` or `S: M` ... LL | a.f(); | ^ method cannot be called on `S` due to unsatisfied trait bounds diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr index e2a80dbffdeaa..29b19d5e3b45b 100644 --- a/tests/ui/iterators/vec-on-unimplemented.stderr +++ b/tests/ui/iterators/vec-on-unimplemented.stderr @@ -3,9 +3,6 @@ error[E0599]: `Vec` is not an iterator | LL | vec![true, false].map(|v| !v).collect::>(); | ^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - | - = note: doesn't satisfy `Vec: Iterator` | = note: the following trait bounds were not satisfied: `Vec: Iterator` diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr index 292525daa3d6b..6d23319ca7e64 100644 --- a/tests/ui/mismatched_types/issue-36053-2.stderr +++ b/tests/ui/mismatched_types/issue-36053-2.stderr @@ -21,11 +21,7 @@ error[E0599]: the method `count` exists for struct `Filter>, {cl LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | --------- ^^^^^ method cannot be called due to unsatisfied trait bounds | | - | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` - | doesn't satisfy `_: FnMut<(&&str,)>` - --> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL - | - = note: doesn't satisfy `_: Iterator` + | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` or `_: FnMut<(&&str,)>` | = note: the following trait bounds were not satisfied: `<{closure@$DIR/issue-36053-2.rs:7:39: 7:48} as FnOnce<(&&str,)>>::Output = bool` diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr index e2db0da74f022..9d6d29ec74eec 100644 --- a/tests/ui/suggestions/derive-trait-for-method-call.stderr +++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr @@ -2,10 +2,7 @@ error[E0599]: the method `test` exists for struct `Foo`, but it --> $DIR/derive-trait-for-method-call.rs:28:15 | LL | enum Enum { - | --------- - | | - | doesn't satisfy `Enum: Clone` - | doesn't satisfy `Enum: Default` + | --------- doesn't satisfy `Enum: Clone` or `Enum: Default` ... LL | enum CloneEnum { | -------------- doesn't satisfy `CloneEnum: Default` @@ -40,10 +37,7 @@ error[E0599]: the method `test` exists for struct `Foo`, bu --> $DIR/derive-trait-for-method-call.rs:34:15 | LL | struct Struct { - | ------------- - | | - | doesn't satisfy `Struct: Clone` - | doesn't satisfy `Struct: Default` + | ------------- doesn't satisfy `Struct: Clone` or `Struct: Default` ... LL | struct CloneStruct { | ------------------ doesn't satisfy `CloneStruct: Default` @@ -85,12 +79,6 @@ LL | struct Foo (X, Y); ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo, Instant>` due to unsatisfied trait bounds - --> $SRC_DIR/std/src/time.rs:LL:COL - | - = note: doesn't satisfy `Instant: Default` - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - | - = note: doesn't satisfy `Vec: Clone` | note: the following trait bounds were not satisfied: `Instant: Default` diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr index 94710f4503f56..09a9b1d3b3482 100644 --- a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -25,9 +25,6 @@ error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, | LL | writeln!(fp, "hello world").unwrap(); | ---------^^---------------- method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds - --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL - | - = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write` | note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method --> $DIR/mut-borrow-needed-by-trait.rs:21:14 diff --git a/tests/ui/suggestions/suggest-change-mut.stderr b/tests/ui/suggestions/suggest-change-mut.stderr index d194afeaf931d..216d1e810fd72 100644 --- a/tests/ui/suggestions/suggest-change-mut.stderr +++ b/tests/ui/suggestions/suggest-change-mut.stderr @@ -27,9 +27,6 @@ error[E0599]: the method `read_until` exists for struct `BufReader<&T>`, but its | LL | stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed"); | ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds - --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL - | - = note: doesn't satisfy `BufReader<&T>: BufRead` | = note: the following trait bounds were not satisfied: `&T: std::io::Read` diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr index 89477475970f4..822fc91e43fea 100644 --- a/tests/ui/traits/track-obligations.stderr +++ b/tests/ui/traits/track-obligations.stderr @@ -2,10 +2,7 @@ error[E0599]: the method `check` exists for struct `Client<()>`, but its trait b --> $DIR/track-obligations.rs:83:16 | LL | struct ALayer(C); - | ---------------- - | | - | doesn't satisfy `<_ as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` - | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>` + | ---------------- doesn't satisfy `<_ as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` or `ALayer<()>: ParticularServiceLayer<()>` ... LL | struct Client(C); | ---------------- method `check` not found for this struct diff --git a/tests/ui/typeck/derive-sugg-arg-arity.stderr b/tests/ui/typeck/derive-sugg-arg-arity.stderr index 41b16a772ca95..46421ba942c57 100644 --- a/tests/ui/typeck/derive-sugg-arg-arity.stderr +++ b/tests/ui/typeck/derive-sugg-arg-arity.stderr @@ -5,8 +5,7 @@ LL | pub struct A; | ------------ | | | function or associated item `partial_cmp` not found for this struct - | doesn't satisfy `A: Iterator` - | doesn't satisfy `A: PartialOrd<_>` + | doesn't satisfy `A: Iterator` or `A: PartialOrd<_>` ... LL | _ => match A::partial_cmp() {}, | ^^^^^^^^^^^ function or associated item cannot be called on `A` due to unsatisfied trait bounds diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr index d65c4306a5f28..0983147a5f0c5 100644 --- a/tests/ui/typeck/issue-31173.stderr +++ b/tests/ui/typeck/issue-31173.stderr @@ -35,12 +35,6 @@ LL | | .collect(); | | -^^^^^^^ method cannot be called due to unsatisfied trait bounds | |_________| | - --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL - | - = note: doesn't satisfy `<_ as Iterator>::Item = &_` - --> $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL - | - = note: doesn't satisfy `_: Iterator` | = note: the following trait bounds were not satisfied: `, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_` From 7df4a09fc4e236f854273202e124747d47246ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 26 Jan 2024 20:44:43 +0000 Subject: [PATCH 277/676] Use single label for method not found due to unmet bound --- .../rustc_hir_typeck/src/method/suggest.rs | 35 ++++++++++++------- .../derives/derive-assoc-type-not-impl.stderr | 5 +-- .../deriving-with-repr-packed-2.stderr | 5 +-- ...gat-bound-during-assoc-ty-selection.stderr | 5 +-- ...method-unsatisfied-assoc-type-predicate.rs | 3 +- ...od-unsatisfied-assoc-type-predicate.stderr | 7 ++-- .../trait-bounds/issue-30786.stderr | 10 ++---- tests/ui/methods/method-call-err-msg.stderr | 5 +-- ...pecialization-trait-not-implemented.stderr | 5 +-- ...impl-derived-implicit-sized-bound-2.stderr | 5 +-- .../impl-derived-implicit-sized-bound.stderr | 5 +-- tests/ui/typeck/derive-sugg-arg-arity.stderr | 5 +-- tests/ui/union/union-derive-clone.stderr | 5 +-- 13 files changed, 37 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index d7a0565895d3e..0499a46dbb826 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -459,22 +459,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - let ty_span = match rcvr_ty.kind() { + let mut ty_span = match rcvr_ty.kind() { ty::Param(param_type) => { Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id())) } ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())), _ => None, }; - if let Some(span) = ty_span { - err.span_label( - span, - format!( - "{item_kind} `{item_name}` not found for this {}", - rcvr_ty.prefix_string(self.tcx) - ), - ); - } if let SelfSource::MethodCall(rcvr_expr) = source { self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| { @@ -1190,13 +1181,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !tcx.sess.source_map().is_span_accessible(span) { continue; } + let pre = if Some(span) == ty_span { + ty_span.take(); + format!( + "{item_kind} `{item_name}` not found for this {} because it ", + rcvr_ty.prefix_string(self.tcx) + ) + } else { + String::new() + }; let msg = match &bounds[..] { - [bound] => format!("doesn't satisfy {bound}"), - [bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")), + [bound] => format!("{pre}doesn't satisfy {bound}"), + [bounds @ .., last] => { + format!("{pre}doesn't satisfy {} or {last}", bounds.join(", ")) + } [] => unreachable!(), }; err.span_label(span, msg); } + if let Some(span) = ty_span { + err.span_label( + span, + format!( + "{item_kind} `{item_name}` not found for this {}", + rcvr_ty.prefix_string(self.tcx) + ), + ); + } if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params { } else { diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 6cbcb455f87e9..61268ffc7f852 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -2,10 +2,7 @@ error[E0599]: the method `clone` exists for struct `Bar`, but its trai --> $DIR/derive-assoc-type-not-impl.rs:18:30 | LL | struct Bar { - | ------------------ - | | - | method `clone` not found for this struct - | doesn't satisfy `Bar: Clone` + | ------------------ method `clone` not found for this struct because it doesn't satisfy `Bar: Clone` ... LL | struct NotClone; | --------------- doesn't satisfy `NotClone: Clone` diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index 172dd80fe1d09..96f51a4e7a2b4 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -2,10 +2,7 @@ error[E0599]: the method `clone` exists for struct `Foo`, but its trait --> $DIR/deriving-with-repr-packed-2.rs:18:11 | LL | pub struct Foo(T, T, T); - | ----------------- - | | - | method `clone` not found for this struct - | doesn't satisfy `Foo: Clone` + | ----------------- method `clone` not found for this struct because it doesn't satisfy `Foo: Clone` LL | LL | struct NonCopy; | -------------- doesn't satisfy `NonCopy: Clone` or `NonCopy: Copy` diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr index 2ce10ce9c1cc0..7813370ae63f8 100644 --- a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr @@ -19,10 +19,7 @@ error[E0599]: the size for values of type `Node` cannot be known --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:31:35 | LL | enum Node { - | ------------------------------ - | | - | variant or associated item `new` not found for this enum - | doesn't satisfy `Node: Sized` + | ------------------------------ variant or associated item `new` not found for this enum because it doesn't satisfy `Node: Sized` ... LL | let mut list = RcNode::::new(); | ^^^ doesn't have a size known at compile-time diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs index 1f9e4f24b161c..add4d58f86a0d 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs @@ -16,8 +16,7 @@ impl = i32>> M for T {} //~| NOTE struct S; -//~^ NOTE method `f` not found for this -//~| NOTE doesn't satisfy `::Y = i32` or `S: M` +//~^ NOTE method `f` not found for this struct because it doesn't satisfy `::Y = i32` or `S: M` impl X for S { type Y = bool; diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr index 489b2772ad8c3..1dd463f996ce6 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr @@ -1,11 +1,8 @@ error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied - --> $DIR/method-unsatisfied-assoc-type-predicate.rs:27:7 + --> $DIR/method-unsatisfied-assoc-type-predicate.rs:26:7 | LL | struct S; - | -------- - | | - | method `f` not found for this struct - | doesn't satisfy `::Y = i32` or `S: M` + | -------- method `f` not found for this struct because it doesn't satisfy `::Y = i32` or `S: M` ... LL | a.f(); | ^ method cannot be called on `S` due to unsatisfied trait bounds diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr index 4f9ceb577c0be..73870703cfbac 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr @@ -2,10 +2,7 @@ error[E0599]: the method `filterx` exists for struct `Map $DIR/issue-30786.rs:120:22 | LL | pub struct Map { - | -------------------- - | | - | method `filterx` not found for this struct - | doesn't satisfy `_: StreamExt` + | -------------------- method `filterx` not found for this struct because it doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds @@ -23,10 +20,7 @@ error[E0599]: the method `countx` exists for struct `Filter $DIR/issue-30786.rs:132:24 | LL | pub struct Filter { - | ----------------------- - | | - | method `countx` not found for this struct - | doesn't satisfy `_: StreamExt` + | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt` ... LL | let count = filter.countx(); | ^^^^^^ method cannot be called due to unsatisfied trait bounds diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr index bd51378cf1a50..f431085745405 100644 --- a/tests/ui/methods/method-call-err-msg.stderr +++ b/tests/ui/methods/method-call-err-msg.stderr @@ -49,10 +49,7 @@ error[E0599]: `Foo` is not an iterator --> $DIR/method-call-err-msg.rs:19:7 | LL | pub struct Foo; - | -------------- - | | - | method `take` not found for this struct - | doesn't satisfy `Foo: Iterator` + | -------------- method `take` not found for this struct because it doesn't satisfy `Foo: Iterator` ... LL | / y.zero() LL | | .take() diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 75c91e4806f77..e9b0845ccf707 100644 --- a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -12,10 +12,7 @@ error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait b --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | struct MyStruct; - | --------------- - | | - | method `foo_one` not found for this struct - | doesn't satisfy `MyStruct: Foo` + | --------------- method `foo_one` not found for this struct because it doesn't satisfy `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr index 84c2ab68da958..397e80197b952 100644 --- a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr +++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr @@ -2,10 +2,7 @@ error[E0599]: the method `get` exists for struct `Victim<'_, Self>`, but its tra --> $DIR/impl-derived-implicit-sized-bound-2.rs:28:19 | LL | struct Victim<'a, T: Perpetrator + ?Sized> { - | ------------------------------------------ - | | - | method `get` not found for this struct - | doesn't satisfy `Victim<'_, Self>: VictimTrait` + | ------------------------------------------ method `get` not found for this struct because it doesn't satisfy `Victim<'_, Self>: VictimTrait` ... LL | self.getter().get(); | ^^^ method cannot be called on `Victim<'_, Self>` due to unsatisfied trait bounds diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr index c597ad0b572ee..abcd915c699c4 100644 --- a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr +++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr @@ -2,10 +2,7 @@ error[E0599]: the method `get` exists for struct `Victim<'_, Self>`, but its tra --> $DIR/impl-derived-implicit-sized-bound.rs:31:19 | LL | struct Victim<'a, T: Perpetrator + ?Sized> - | ------------------------------------------ - | | - | method `get` not found for this struct - | doesn't satisfy `Victim<'_, Self>: VictimTrait` + | ------------------------------------------ method `get` not found for this struct because it doesn't satisfy `Victim<'_, Self>: VictimTrait` ... LL | self.getter().get(); | ^^^ method cannot be called on `Victim<'_, Self>` due to unsatisfied trait bounds diff --git a/tests/ui/typeck/derive-sugg-arg-arity.stderr b/tests/ui/typeck/derive-sugg-arg-arity.stderr index 46421ba942c57..382b324c4cc50 100644 --- a/tests/ui/typeck/derive-sugg-arg-arity.stderr +++ b/tests/ui/typeck/derive-sugg-arg-arity.stderr @@ -2,10 +2,7 @@ error[E0599]: the function or associated item `partial_cmp` exists for struct `A --> $DIR/derive-sugg-arg-arity.rs:5:23 | LL | pub struct A; - | ------------ - | | - | function or associated item `partial_cmp` not found for this struct - | doesn't satisfy `A: Iterator` or `A: PartialOrd<_>` + | ------------ function or associated item `partial_cmp` not found for this struct because it doesn't satisfy `A: Iterator` or `A: PartialOrd<_>` ... LL | _ => match A::partial_cmp() {}, | ^^^^^^^^^^^ function or associated item cannot be called on `A` due to unsatisfied trait bounds diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index 39f1e32e6eb71..a2b81f0dba1c3 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -17,10 +17,7 @@ error[E0599]: the method `clone` exists for union `U5`, but its tra --> $DIR/union-derive-clone.rs:35:15 | LL | union U5 { - | ----------- - | | - | method `clone` not found for this union - | doesn't satisfy `U5: Clone` + | ----------- method `clone` not found for this union because it doesn't satisfy `U5: Clone` ... LL | struct CloneNoCopy; | ------------------ doesn't satisfy `CloneNoCopy: Copy` From 40f5e6899d00484f05a3f1b227180a69a43bea0f Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 28 Dec 2023 16:20:02 -0800 Subject: [PATCH 278/676] 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 279/676] 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 280/676] 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 a5d9def321df76de6fb90ed836bf062b557636d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 22 Nov 2023 19:53:24 +0000 Subject: [PATCH 281/676] Properly recover from trailing attr in body When encountering an attribute in a body, we try to recover from an attribute on an expression (as opposed to a statement). We need to properly clean up when the attribute is at the end of the body where a tail expression would be. Fix #118164. --- .../rustc_parse/src/parser/diagnostics.rs | 19 +++++++++++-- ...r-from-trailing-outer-attribute-in-body.rs | 9 +++++++ ...om-trailing-outer-attribute-in-body.stderr | 27 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs create mode 100644 tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 720a610fdf518..1924d28d91c9c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -792,13 +792,28 @@ impl<'a> Parser<'a> { && let [segment] = &attr_kind.item.path.segments[..] && segment.ident.name == sym::cfg && let Some(args_span) = attr_kind.item.args.span() - && let Ok(next_attr) = snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None)) + && let next_attr = match snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None)) + { + Ok(next_attr) => next_attr, + Err(inner_err) => { + err.cancel(); + inner_err.cancel(); + return; + } + } && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind && let Some(next_attr_args_span) = next_attr_kind.item.args.span() && let [next_segment] = &next_attr_kind.item.path.segments[..] && segment.ident.name == sym::cfg - && let Ok(next_expr) = snapshot.parse_expr() { + let next_expr = match snapshot.parse_expr() { + Ok(next_expr) => next_expr, + Err(inner_err) => { + err.cancel(); + inner_err.cancel(); + return; + } + }; // We have for sure // #[cfg(..)] // expr diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs new file mode 100644 index 0000000000000..a7412f51782fb --- /dev/null +++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs @@ -0,0 +1,9 @@ +// Issue #118164: recovery path leaving unemitted error behind +fn bar() -> String { + #[cfg(feature = )] + [1, 2, 3].iter().map().collect::() //~ ERROR expected `;`, found `#` + #[attr] //~ ERROR expected statement after outer attribute +} +fn main() { + let _ = bar(); +} diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr new file mode 100644 index 0000000000000..dd0081cc2dff9 --- /dev/null +++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr @@ -0,0 +1,27 @@ +error: expected `;`, found `#` + --> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:4:47 + | +LL | #[cfg(feature = )] + | ------------------ only `;` terminated statements or tail expressions are allowed after this attribute +LL | [1, 2, 3].iter().map().collect::() + | ^ expected `;` here +LL | #[attr] + | - unexpected token + | +help: add `;` here + | +LL | [1, 2, 3].iter().map().collect::(); + | + +help: alternatively, consider surrounding the expression with a block + | +LL | { [1, 2, 3].iter().map().collect::() } + | + + + +error: expected statement after outer attribute + --> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:5:5 + | +LL | #[attr] + | ^^^^^^^ + +error: aborting due to 2 previous errors + From ad5e2cfa3b9fe079e962e806e59cf92f030984d1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 27 Jan 2024 02:00:36 +0200 Subject: [PATCH 282/676] 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 8b3a681a34ed183510af5365e9fab17cca06baf7 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sat, 27 Jan 2024 10:24:45 +0800 Subject: [PATCH 283/676] minor: pick a suitable var name --- compiler/rustc_hir_typeck/src/method/suggest.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index bbebc4752790c..8feef6bc97e95 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1588,7 +1588,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let SelfSource::MethodCall(_) = source { let first_arg = static_candidates.get(0).and_then(|candidate_source| { - let (assoc_did, impl_ty) = match candidate_source { + let (assoc_did, self_ty) = match candidate_source { CandidateSource::Impl(impl_did) => { (*impl_did, self.tcx.type_of(*impl_did).instantiate_identity()) } @@ -1606,7 +1606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sig.inputs().skip_binder().get(0).and_then(|first| { // if the type of first arg is the same as the current impl type, we should take the first arg into assoc function let first_ty = first.peel_refs(); - if first_ty == impl_ty || first_ty == self.tcx.types.self_param { + if first_ty == self_ty || first_ty == self.tcx.types.self_param { Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str())) } else { None From e26f213050f451ec3e9c6a3132bc0d5be5123737 Mon Sep 17 00:00:00 2001 From: "HTGAzureX1212." <39023054+HTGAzureX1212@users.noreply.github.com> Date: Sat, 27 Jan 2024 12:28:28 +0800 Subject: [PATCH 284/676] make modifications as per reviews --- library/std/src/sys/pal/windows/fs.rs | 46 +++++++++++++++------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 38835db7649de..1a8151479f390 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -1069,26 +1069,6 @@ pub fn readdir(p: &Path) -> io::Result { let mut wfd = mem::zeroed(); let find_handle = c::FindFirstFileW(path.as_ptr(), &mut wfd); - // The status `ERROR_FILE_NOT_FOUND` is returned by the `FindFirstFileW` function - // if no matching files can be found, but not necessarily that the path to find the - // files in does not exist. - // - // Hence, a check for whether the path to search in exists is added when the last - // os error returned by Windows is `ERROR_FILE_NOT_FOUND` to handle this scenario. - // If that is the case, an empty `ReadDir` iterator is returned as it returns `None` - // in the initial `.next()` invocation because `ERROR_NO_MORE_FILES` would have been - // returned by the `FindNextFileW` function. - // - // See issue #120040: https://github.com/rust-lang/rust/issues/120040. - let last_error = Error::last_os_error(); - if last_error.raw_os_error().unwrap() == c::ERROR_FILE_NOT_FOUND as i32 && p.exists() { - return Ok(ReadDir { - handle: FindNextFileHandle(find_handle), - root: Arc::new(root), - first: None, - }); - } - if find_handle != c::INVALID_HANDLE_VALUE { Ok(ReadDir { handle: FindNextFileHandle(find_handle), @@ -1096,7 +1076,31 @@ pub fn readdir(p: &Path) -> io::Result { first: Some(wfd), }) } else { - Err(last_error) + // The status `ERROR_FILE_NOT_FOUND` is returned by the `FindFirstFileW` function + // if no matching files can be found, but not necessarily that the path to find the + // files in does not exist. + // + // Hence, a check for whether the path to search in exists is added when the last + // os error returned by Windows is `ERROR_FILE_NOT_FOUND` to handle this scenario. + // If that is the case, an empty `ReadDir` iterator is returned as it returns `None` + // in the initial `.next()` invocation because `ERROR_NO_MORE_FILES` would have been + // returned by the `FindNextFileW` function. + // + // See issue #120040: https://github.com/rust-lang/rust/issues/120040. + let last_error = api::get_last_error(); + if last_error.code == c::ERROR_FILE_NOT_FOUND { + return Ok(ReadDir { + handle: FindNextFileHandle(find_handle), + root: Arc::new(root), + first: None, + }); + } + + // Just return the error constructed from the raw OS error if the above is not the case. + // + // Note: `ERROR_PATH_NOT_FOUND` would have been returned by the `FindFirstFileW` function + // when the path to search in does not exist in the first place. + Err(Error::from_raw_os_error(last_error.code as i32)); } } } From 018bf305cdcc2d478998642bc2d9a5613ec902f3 Mon Sep 17 00:00:00 2001 From: "HTGAzureX1212." <39023054+HTGAzureX1212@users.noreply.github.com> Date: Sat, 27 Jan 2024 12:43:38 +0800 Subject: [PATCH 285/676] add extra check for invalid handle in ReadDir::next --- library/std/src/sys/pal/windows/fs.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 1a8151479f390..2bdd3d96fa48c 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -112,6 +112,13 @@ impl fmt::Debug for ReadDir { impl Iterator for ReadDir { type Item = io::Result; fn next(&mut self) -> Option> { + if self.handle.0 == c::INVALID_HANDLE_VALUE { + // This iterator was initialized with an `INVALID_HANDLE_VALUE` as its handle. + // Simply return `None` because this is only the case when `FindFirstFileW` in + // the construction of this iterator returns `ERROR_FILE_NOT_FOUND` which means + // no matchhing files can be found. + return None; + } if let Some(first) = self.first.take() { if let Some(e) = DirEntry::new(&self.root, &first) { return Some(Ok(e)); @@ -1100,7 +1107,7 @@ pub fn readdir(p: &Path) -> io::Result { // // Note: `ERROR_PATH_NOT_FOUND` would have been returned by the `FindFirstFileW` function // when the path to search in does not exist in the first place. - Err(Error::from_raw_os_error(last_error.code as i32)); + Err(Error::from_raw_os_error(last_error.code as i32)) } } } From 8a5829cf286c8361d93aab090bbf4fc599e37fef Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 26 Jan 2024 20:08:10 +0100 Subject: [PATCH 286/676] 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 287/676] 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 3cc0f02dac78a1af69e395e2449f66d14926bb21 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jan 2024 12:48:52 +0100 Subject: [PATCH 288/676] fix typo in operator.rs --- src/tools/miri/src/operator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs index 140764446969a..6f19dead2e9bf 100644 --- a/src/tools/miri/src/operator.rs +++ b/src/tools/miri/src/operator.rs @@ -24,7 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(match bin_op { Eq | Ne | Lt | Le | Gt | Ge => { - assert_eq!(left.layout.abi, right.layout.abi); // types an differ, e.g. fn ptrs with different `for` + assert_eq!(left.layout.abi, right.layout.abi); // types can differ, e.g. fn ptrs with different `for` let size = this.pointer_size(); // Just compare the bits. ScalarPairs are compared lexicographically. // We thus always compare pairs and simply fill scalars up with 0. From f5c78955c88ac37b7422bef6ee9ec993c0a5dad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sat, 27 Jan 2024 14:18:33 +0200 Subject: [PATCH 289/676] Stop using derivative in rustc_pattern_analysis --- Cargo.lock | 1 - compiler/rustc_pattern_analysis/Cargo.toml | 1 - .../rustc_pattern_analysis/src/constructor.rs | 98 ++++++++++++++++++- compiler/rustc_pattern_analysis/src/lib.rs | 20 +++- compiler/rustc_pattern_analysis/src/pat.rs | 31 +++++- compiler/rustc_pattern_analysis/src/rustc.rs | 8 +- .../rustc_pattern_analysis/src/usefulness.rs | 58 ++++++++--- 7 files changed, 191 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28068684362e4..587489a94b20e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4342,7 +4342,6 @@ dependencies = [ name = "rustc_pattern_analysis" version = "0.0.0" dependencies = [ - "derivative", "rustc-hash", "rustc_apfloat", "rustc_arena", diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index 1d0e1cb7e6a57..b9bdcb41929dc 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -derivative = "2.2.0" rustc-hash = "1.1.0" rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena", optional = true } diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index e94a0373c79ff..4996015f86345 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -151,6 +151,7 @@ use std::cmp::{self, max, min, Ordering}; use std::fmt; use std::iter::once; +use std::mem; use smallvec::SmallVec; @@ -648,8 +649,6 @@ 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(derivative::Derivative)] -#[derivative(Debug(bound = ""), Clone(bound = ""), PartialEq(bound = ""))] pub enum Constructor { /// Tuples and structs. Struct, @@ -692,6 +691,101 @@ pub enum Constructor { Missing, } +impl Clone for Constructor { + fn clone(&self) -> Self { + match self { + Constructor::Struct => Constructor::Struct, + Constructor::Variant(idx) => Constructor::Variant(idx.clone()), + Constructor::Ref => Constructor::Ref, + Constructor::Slice(slice) => Constructor::Slice(slice.clone()), + Constructor::UnionField => Constructor::UnionField, + Constructor::Bool(b) => Constructor::Bool(b.clone()), + Constructor::IntRange(range) => Constructor::IntRange(range.clone()), + Constructor::F32Range(lo, hi, end) => { + Constructor::F32Range(lo.clone(), hi.clone(), end.clone()) + } + Constructor::F64Range(lo, hi, end) => { + Constructor::F64Range(lo.clone(), hi.clone(), end.clone()) + } + Constructor::Str(value) => Constructor::Str(value.clone()), + Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()), + Constructor::Or => Constructor::Or, + Constructor::Wildcard => Constructor::Wildcard, + Constructor::NonExhaustive => Constructor::NonExhaustive, + Constructor::Hidden => Constructor::Hidden, + Constructor::Missing => Constructor::Missing, + } + } +} + +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 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) diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 6374874165fc1..a53d7a0d8096a 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -136,23 +136,35 @@ pub trait TypeCx: Sized + fmt::Debug { } /// Context that provides information global to a match. -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""))] 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)] -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""))] pub struct MatchArm<'p, Cx: TypeCx> { pub pat: &'p DeconstructedPat<'p, Cx>, pub has_guard: bool, pub arm_data: Cx::ArmData, } +impl<'p, Cx: TypeCx> Clone for MatchArm<'p, Cx> { + fn clone(&self) -> Self { + Self { pat: self.pat, has_guard: self.has_guard, arm_data: self.arm_data } + } +} + +impl<'p, Cx: TypeCx> Copy for MatchArm<'p, Cx> {} + /// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are /// useful, and runs some lints. #[cfg(feature = "rustc")] diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 1cc3107455645..d476766d466f2 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -218,8 +218,6 @@ impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> { /// algorithm. Do not use `Wild` to represent a wildcard pattern comping from user input. /// /// This is morally `Option<&'p DeconstructedPat>` where `None` is interpreted as a wildcard. -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""))] pub(crate) enum PatOrWild<'p, Cx: TypeCx> { /// A non-user-provided wildcard, created during specialization. Wild, @@ -227,6 +225,17 @@ pub(crate) enum PatOrWild<'p, Cx: TypeCx> { Pat(&'p DeconstructedPat<'p, Cx>), } +impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { + fn clone(&self) -> Self { + match self { + PatOrWild::Wild => PatOrWild::Wild, + PatOrWild::Pat(pat) => PatOrWild::Pat(pat), + } + } +} + +impl<'p, Cx: TypeCx> Copy for PatOrWild<'p, Cx> {} + impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<'p, Cx>> { match self { @@ -289,14 +298,28 @@ 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(derivative::Derivative)] -#[derivative(Debug(bound = ""), Clone(bound = ""))] pub struct WitnessPat { ctor: Constructor, pub(crate) fields: Vec>, ty: Cx::Ty, } +impl Clone for WitnessPat { + fn clone(&self) -> Self { + Self { ctor: self.ctor.clone(), fields: self.fields.clone(), ty: self.ty.clone() } + } +} + +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/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index ef90d24b0bf1e..223d6cefc83fe 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -46,11 +46,15 @@ pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat`. #[repr(transparent)] -#[derive(derivative::Derivative)] #[derive(Clone, Copy)] -#[derivative(Debug = "transparent")] pub struct RevealedTy<'tcx>(Ty<'tcx>); +impl<'tcx> fmt::Debug for RevealedTy<'tcx> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(fmt) + } +} + impl<'tcx> std::ops::Deref for RevealedTy<'tcx> { type Target = Ty<'tcx>; fn deref(&self) -> &Self::Target { diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index a627bdeef81e3..b15de1c0ca9d7 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -731,16 +731,26 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { } /// Context that provides information local to a place under investigation. -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))] pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> { - #[derivative(Debug = "ignore")] pub(crate) mcx: MatchCtxt<'a, Cx>, /// Type of the place under investigation. - #[derivative(Clone(clone_with = "Clone::clone"))] // See rust-derivative#90 pub(crate) ty: &'a Cx::Ty, } +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() + } +} + 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))] @@ -813,8 +823,6 @@ impl fmt::Display for ValidityConstraint { // The three lifetimes are: // - 'p coming from the input // - Cx global compilation context -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""))] struct PatStack<'p, Cx: TypeCx> { // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well. pats: SmallVec<[PatOrWild<'p, Cx>; 2]>, @@ -824,6 +832,12 @@ struct PatStack<'p, Cx: TypeCx> { relevant: bool, } +impl<'p, Cx: TypeCx> Clone for PatStack<'p, Cx> { + fn clone(&self) -> Self { + Self { pats: self.pats.clone(), relevant: self.relevant } + } +} + impl<'p, Cx: TypeCx> PatStack<'p, Cx> { fn from_pattern(pat: &'p DeconstructedPat<'p, Cx>) -> Self { PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true } @@ -1184,10 +1198,20 @@ 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(derivative::Derivative)] -#[derivative(Debug(bound = ""), Clone(bound = ""))] struct WitnessStack(Vec>); +impl Clone for WitnessStack { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +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 { @@ -1232,18 +1256,28 @@ 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(derivative::Derivative)] -#[derivative(Debug(bound = ""), Clone(bound = ""))] struct WitnessMatrix(Vec>); +impl Clone for WitnessMatrix { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +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 { - WitnessMatrix(vec![]) + WitnessMatrix(Vec::new()) } /// New matrix with one `()` witness, i.e. with no columns. fn unit_witness() -> Self { - WitnessMatrix(vec![WitnessStack(vec![])]) + WitnessMatrix(vec![WitnessStack(Vec::new())]) } /// Whether this has any witnesses. From 57934ac47a4e0a14237103a1745c49187af7f048 Mon Sep 17 00:00:00 2001 From: Alain Siegrist Date: Sun, 8 Oct 2023 23:15:04 +0200 Subject: [PATCH 290/676] 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 291/676] 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 292/676] 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 cda898b0d9a34e4a3615e879fcd4fb2da3fcead5 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sat, 27 Jan 2024 14:55:15 +0100 Subject: [PATCH 293/676] Remove unnecessary unit returns in query declarations For consistency with normal functions. --- compiler/rustc_middle/src/query/mod.rs | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1122f571fff8a..b383a6f5e52c8 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -109,7 +109,7 @@ pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue // as they will raise an fatal error on query cycles instead. rustc_queries! { /// This exists purely for testing the interactions between span_delayed_bug and incremental. - query trigger_span_delayed_bug(key: DefId) -> () { + query trigger_span_delayed_bug(key: DefId) { desc { "triggering a span delayed bug for testing incremental" } } @@ -119,7 +119,7 @@ rustc_queries! { desc { "compute registered tools for crate" } } - query early_lint_checks(_: ()) -> () { + query early_lint_checks(_: ()) { desc { "perform lints prior to macro expansion" } } @@ -299,7 +299,7 @@ rustc_queries! { /// name. This is useful for cases were not all linting code from rustc /// was called. With the default `None` all registered lints will also /// be checked for expectation fulfillment. - query check_expectations(key: Option) -> () { + query check_expectations(key: Option) { eval_always desc { "checking lint expectations (RFC 2383)" } } @@ -906,39 +906,39 @@ rustc_queries! { } /// Performs lint checking for the module. - query lint_mod(key: LocalModDefId) -> () { + query lint_mod(key: LocalModDefId) { desc { |tcx| "linting {}", describe_as_module(key, tcx) } } - query check_unused_traits(_: ()) -> () { + query check_unused_traits(_: ()) { desc { "checking unused trait imports in crate" } } /// Checks the attributes in the module. - query check_mod_attrs(key: LocalModDefId) -> () { + query check_mod_attrs(key: LocalModDefId) { desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } } /// Checks for uses of unstable APIs in the module. - query check_mod_unstable_api_usage(key: LocalModDefId) -> () { + query check_mod_unstable_api_usage(key: LocalModDefId) { desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) } } /// Checks the const bodies in the module for illegal operations (e.g. `if` or `loop`). - query check_mod_const_bodies(key: LocalModDefId) -> () { + query check_mod_const_bodies(key: LocalModDefId) { desc { |tcx| "checking consts in {}", describe_as_module(key, tcx) } } /// Checks the loops in the module. - query check_mod_loops(key: LocalModDefId) -> () { + query check_mod_loops(key: LocalModDefId) { desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) } } - query check_mod_naked_functions(key: LocalModDefId) -> () { + query check_mod_naked_functions(key: LocalModDefId) { desc { |tcx| "checking naked functions in {}", describe_as_module(key, tcx) } } - query check_mod_privacy(key: LocalModDefId) -> () { + query check_mod_privacy(key: LocalModDefId) { desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) } } @@ -958,7 +958,7 @@ rustc_queries! { desc { "finding live symbols in crate" } } - query check_mod_deathness(key: LocalModDefId) -> () { + query check_mod_deathness(key: LocalModDefId) { desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } } @@ -972,7 +972,7 @@ rustc_queries! { ensure_forwards_result_if_red } - query collect_mod_item_types(key: LocalModDefId) -> () { + query collect_mod_item_types(key: LocalModDefId) { desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) } } @@ -1121,7 +1121,7 @@ rustc_queries! { eval_always desc { "checking effective visibilities" } } - query check_private_in_public(_: ()) -> () { + query check_private_in_public(_: ()) { eval_always desc { "checking for private elements in public interfaces" } } From b22e772cab8ea0673f25fdacf3e1af472b242818 Mon Sep 17 00:00:00 2001 From: YangzeLuo Date: Sat, 27 Jan 2024 23:36:01 +0800 Subject: [PATCH 294/676] 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 4f0ce6fca2426427aab225cf1138a9171edb63b8 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 20 Jan 2024 18:02:56 +0100 Subject: [PATCH 295/676] Switch `NonZero` alias direction. --- library/core/src/num/mod.rs | 10 ++++++- library/core/src/num/nonzero.rs | 50 +++++++++++++++++++++------------ library/std/src/lib.rs | 1 + library/std/src/num.rs | 10 +++++++ 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index c2b646b9b3e4a..03c977abbbb42 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -61,7 +61,15 @@ pub use dec2flt::ParseFloatError; #[stable(feature = "rust1", since = "1.0.0")] pub use error::ParseIntError; -pub(crate) use nonzero::NonZero; +#[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" +)] +pub use nonzero::ZeroablePrimitive; + +#[unstable(feature = "generic_nonzero", issue = "120257")] +pub use nonzero::NonZero; #[stable(feature = "nonzero", since = "1.28.0")] pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 45ac544ceaaca..1124719fc8df1 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -3,6 +3,8 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash::{Hash, Hasher}; +#[cfg(bootstrap)] +use crate::marker::StructuralEq; use crate::marker::StructuralPartialEq; use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem}; use crate::str::FromStr; @@ -30,9 +32,7 @@ mod private { issue = "none" )] #[const_trait] -pub trait ZeroablePrimitive: Sized + Copy + private::Sealed { - type NonZero; -} +pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {} macro_rules! impl_zeroable_primitive { ($NonZero:ident ( $primitive:ty )) => { @@ -48,9 +48,7 @@ macro_rules! impl_zeroable_primitive { reason = "implementation detail which may disappear or be replaced at any time", issue = "none" )] - impl const ZeroablePrimitive for $primitive { - type NonZero = $NonZero; - } + impl const ZeroablePrimitive for $primitive {} }; } @@ -67,12 +65,23 @@ impl_zeroable_primitive!(NonZeroI64(i64)); impl_zeroable_primitive!(NonZeroI128(i128)); impl_zeroable_primitive!(NonZeroIsize(isize)); -#[unstable( - feature = "nonzero_internals", - reason = "implementation detail which may disappear or be replaced at any time", - issue = "none" -)] -pub(crate) type NonZero = ::NonZero; +/// A value that is known not to equal zero. +/// +/// This enables some memory layout optimization. +/// For example, `Option>` is the same size as `u32`: +/// +/// ``` +/// #![feature(generic_nonzero)] +/// use core::mem::size_of; +/// +/// assert_eq!(size_of::>>(), size_of::()); +/// ``` +#[unstable(feature = "generic_nonzero", issue = "120257")] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_nonnull_optimization_guaranteed] +#[rustc_diagnostic_item = "NonZero"] +pub struct NonZero(T); macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { @@ -131,12 +140,7 @@ macro_rules! nonzero_integer { /// /// [null pointer optimization]: crate::option#representation #[$stability] - #[derive(Copy, Eq)] - #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start(1)] - #[rustc_nonnull_optimization_guaranteed] - #[rustc_diagnostic_item = stringify!($Ty)] - pub struct $Ty($Int); + pub type $Ty = NonZero<$Int>; impl $Ty { /// Creates a non-zero without checking whether the value is non-zero. @@ -543,6 +547,9 @@ macro_rules! nonzero_integer { } } + #[$stability] + impl Copy for $Ty {} + #[$stability] impl PartialEq for $Ty { #[inline] @@ -559,6 +566,13 @@ macro_rules! nonzero_integer { #[unstable(feature = "structural_match", issue = "31434")] impl StructuralPartialEq for $Ty {} + #[$stability] + impl Eq for $Ty {} + + #[unstable(feature = "structural_match", issue = "31434")] + #[cfg(bootstrap)] + impl StructuralEq for $Ty {} + #[$stability] impl PartialOrd for $Ty { #[inline] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 751e988a99b30..2e458562744bf 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -323,6 +323,7 @@ #![feature(float_gamma)] #![feature(float_minimum_maximum)] #![feature(float_next_up_down)] +#![feature(generic_nonzero)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] #![feature(hint_assert_unchecked)] diff --git a/library/std/src/num.rs b/library/std/src/num.rs index 55f6ddcf77fbf..1343fdfd1dfdd 100644 --- a/library/std/src/num.rs +++ b/library/std/src/num.rs @@ -16,6 +16,16 @@ pub use core::num::Wrapping; #[stable(feature = "rust1", since = "1.0.0")] pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError}; +#[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" +)] +pub use core::num::ZeroablePrimitive; + +#[unstable(feature = "generic_nonzero", issue = "120257")] +pub use core::num::NonZero; + #[stable(feature = "signed_nonzero", since = "1.34.0")] pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; #[stable(feature = "nonzero", since = "1.28.0")] From 554b0f70c30e5f2bff2a472adaf310b36a26d770 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 20 Jan 2024 18:25:52 +0100 Subject: [PATCH 296/676] Add `NonZero` symbol. --- compiler/rustc_span/src/symbol.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 514d65abbe3e6..a54b928b908a7 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -246,17 +246,7 @@ symbols! { MutexGuard, N, NonNull, - NonZeroI128, - NonZeroI16, - NonZeroI32, - NonZeroI64, - NonZeroI8, - NonZeroU128, - NonZeroU16, - NonZeroU32, - NonZeroU64, - NonZeroU8, - NonZeroUsize, + NonZero, None, Normal, Ok, From ca2ec7af35f5a428987fff9ca558e71e79079aff Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 12 May 2023 03:02:46 +0200 Subject: [PATCH 297/676] Fix `NonZero` clippy lints. --- .../src/operators/arithmetic_side_effects.rs | 55 +++++++++++-------- .../transmute/transmute_int_to_non_zero.rs | 51 +++++++++++------ 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index 929efb6c574d5..96ea063aa74d6 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -1,11 +1,11 @@ use super::ARITHMETIC_SIDE_EFFECTS; use clippy_utils::consts::{constant, constant_simple, Constant}; use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::type_diagnostic_name; +use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; @@ -88,37 +88,44 @@ impl ArithmeticSideEffects { } /// Verifies built-in types that have specific allowed operations - fn has_specific_allowed_type_and_operation( - cx: &LateContext<'_>, - lhs_ty: Ty<'_>, + fn has_specific_allowed_type_and_operation<'tcx>( + cx: &LateContext<'tcx>, + lhs_ty: Ty<'tcx>, op: &Spanned, - rhs_ty: Ty<'_>, + rhs_ty: Ty<'tcx>, ) -> bool { let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem); - let is_non_zero_u = |symbol: Option| { - matches!( - symbol, - Some( - sym::NonZeroU128 - | sym::NonZeroU16 - | sym::NonZeroU32 - | sym::NonZeroU64 - | sym::NonZeroU8 - | sym::NonZeroUsize - ) - ) + let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| { + let tcx = cx.tcx; + + let ty::Adt(adt, substs) = ty.kind() else { return false }; + + if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) { + return false; + }; + + let int_type = substs.type_at(0); + let unsigned_int_types = [ + tcx.types.u8, + tcx.types.u16, + tcx.types.u32, + tcx.types.u64, + tcx.types.u128, + tcx.types.usize, + ]; + + unsigned_int_types.contains(&int_type) }; let is_sat_or_wrap = |ty: Ty<'_>| { - let is_sat = type_diagnostic_name(cx, ty) == Some(sym::Saturating); - let is_wrap = type_diagnostic_name(cx, ty) == Some(sym::Wrapping); - is_sat || is_wrap + is_type_diagnostic_item(cx, ty, sym::Saturating) || is_type_diagnostic_item(cx, ty, sym::Wrapping) }; - // If the RHS is NonZeroU*, then division or module by zero will never occur - if is_non_zero_u(type_diagnostic_name(cx, rhs_ty)) && is_div_or_rem { + // If the RHS is `NonZero`, then division or module by zero will never occur. + if is_non_zero_u(cx, rhs_ty) && is_div_or_rem { return true; } - // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module + + // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module. if is_sat_or_wrap(lhs_ty) { return !is_div_or_rem; } diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs index 5df645491ff81..97068efd43cd8 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs @@ -16,40 +16,55 @@ pub(super) fn check<'tcx>( to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, ) -> bool { - let (ty::Int(_) | ty::Uint(_), Some(to_ty_adt)) = (&from_ty.kind(), to_ty.ty_adt_def()) else { + let tcx = cx.tcx; + + let (ty::Int(_) | ty::Uint(_), ty::Adt(adt, substs)) = (&from_ty.kind(), to_ty.kind()) else { return false; }; - let Some(to_type_sym) = cx.tcx.get_diagnostic_name(to_ty_adt.did()) else { + + if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) { return false; }; - if !matches!( - to_type_sym, - sym::NonZeroU8 - | sym::NonZeroU16 - | sym::NonZeroU32 - | sym::NonZeroU64 - | sym::NonZeroU128 - | sym::NonZeroI8 - | sym::NonZeroI16 - | sym::NonZeroI32 - | sym::NonZeroI64 - | sym::NonZeroI128 - ) { + // FIXME: This can be simplified once `NonZero` is stable. + let coercable_types = [ + ("NonZeroU8", tcx.types.u8), + ("NonZeroU16", tcx.types.u16), + ("NonZeroU32", tcx.types.u32), + ("NonZeroU64", tcx.types.u64), + ("NonZeroU128", tcx.types.u128), + ("NonZeroUsize", tcx.types.usize), + ("NonZeroI8", tcx.types.i8), + ("NonZeroI16", tcx.types.i16), + ("NonZeroI32", tcx.types.i32), + ("NonZeroI64", tcx.types.i64), + ("NonZeroI128", tcx.types.i128), + ("NonZeroIsize", tcx.types.isize), + ]; + + let int_type = substs.type_at(0); + + let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| { + if *t == int_type && *t == from_ty { + Some(nonzero_alias) + } else { + None + } + }) else { return false; - } + }; span_lint_and_then( cx, TRANSMUTE_INT_TO_NON_ZERO, e.span, - &format!("transmute from a `{from_ty}` to a `{to_type_sym}`"), + &format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"), |diag| { let arg = sugg::Sugg::hir(cx, arg, ".."); diag.span_suggestion( e.span, "consider using", - format!("{to_type_sym}::{}({arg})", sym::new_unchecked), + format!("{nonzero_alias}::{}({arg})", sym::new_unchecked), Applicability::Unspecified, ); }, From 117eb9f3768e1e9a380de2b4f61a90124e54fd19 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 20 Jan 2024 18:47:22 +0100 Subject: [PATCH 298/676] Fix `NonZero` suggestions. --- .../src/fn_ctxt/suggestions.rs | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 896d000233ae9..95c1139e43e44 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2140,46 +2140,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, ) -> bool { let tcx = self.tcx; - let (adt, unwrap) = match expected.kind() { + let (adt, substs, unwrap) = match expected.kind() { // In case Option is wanted, but * is provided, suggest calling new - ty::Adt(adt, args) if tcx.is_diagnostic_item(sym::Option, adt.did()) => { - // Unwrap option - let ty::Adt(adt, _) = args.type_at(0).kind() else { + ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => { + let nonzero_type = substs.type_at(0); // Unwrap option type. + let ty::Adt(adt, substs) = nonzero_type.kind() else { return false; }; - - (adt, "") + (adt, substs, "") } - // In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types - ty::Adt(adt, _) => (adt, ".unwrap()"), + // In case `NonZero<*>` is wanted but `*` is provided, also add `.unwrap()` to satisfy types. + ty::Adt(adt, substs) => (adt, substs, ".unwrap()"), _ => return false, }; - let map = [ - (sym::NonZeroU8, tcx.types.u8), - (sym::NonZeroU16, tcx.types.u16), - (sym::NonZeroU32, tcx.types.u32), - (sym::NonZeroU64, tcx.types.u64), - (sym::NonZeroU128, tcx.types.u128), - (sym::NonZeroI8, tcx.types.i8), - (sym::NonZeroI16, tcx.types.i16), - (sym::NonZeroI32, tcx.types.i32), - (sym::NonZeroI64, tcx.types.i64), - (sym::NonZeroI128, tcx.types.i128), + if !self.tcx.is_diagnostic_item(sym::NonZero, adt.did()) { + return false; + } + + // FIXME: This can be simplified once `NonZero` is stable. + let coercable_types = [ + ("NonZeroU8", tcx.types.u8), + ("NonZeroU16", tcx.types.u16), + ("NonZeroU32", tcx.types.u32), + ("NonZeroU64", tcx.types.u64), + ("NonZeroU128", tcx.types.u128), + ("NonZeroI8", tcx.types.i8), + ("NonZeroI16", tcx.types.i16), + ("NonZeroI32", tcx.types.i32), + ("NonZeroI64", tcx.types.i64), + ("NonZeroI128", tcx.types.i128), ]; - let Some((s, _)) = map.iter().find(|&&(s, t)| { - self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t) + let int_type = substs.type_at(0); + + let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| { + if *t == int_type && self.can_coerce(expr_ty, *t) { Some(nonzero_alias) } else { None } }) else { return false; }; - let path = self.tcx.def_path_str(adt.non_enum_variant().def_id); - err.multipart_suggestion( - format!("consider calling `{s}::new`"), + format!("consider calling `{nonzero_alias}::new`"), vec![ - (expr.span.shrink_to_lo(), format!("{path}::new(")), + (expr.span.shrink_to_lo(), format!("{nonzero_alias}::new(")), (expr.span.shrink_to_hi(), format!("){unwrap}")), ], Applicability::MaybeIncorrect, From 021739c84021b996e4d65bbd7956dd3c732c6dc2 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 20 Jan 2024 18:55:53 +0100 Subject: [PATCH 299/676] Update tests. --- src/etc/natvis/libcore.natvis | 35 +------------- tests/debuginfo/msvc-pretty-enums.rs | 8 ++-- tests/debuginfo/numeric-types.rs | 46 +++++++++---------- ...ransmutes.adt_transmutes.InstSimplify.diff | 4 +- .../layout/zero-sized-array-enum-niche.stderr | 2 +- tests/ui/lint/clashing-extern-fn.rs | 2 +- tests/ui/lint/clashing-extern-fn.stderr | 6 +-- tests/ui/lint/invalid_value.stderr | 16 +++---- tests/ui/lint/lint-ctypes-enum.stderr | 6 +-- .../non_zero_assigned_something.stderr | 8 ++-- .../not-suggest-float-literal.stderr | 2 +- .../ui/print_type_sizes/niche-filling.stdout | 16 +++---- tests/ui/traits/issue-77982.stderr | 2 +- tests/ui/try-trait/bad-interconversion.stderr | 2 +- 14 files changed, 62 insertions(+), 93 deletions(-) diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index f8569ef2594b4..5e0c21a13a9fe 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -41,40 +41,7 @@ - - {__0} - - - {__0} - - - {__0} - - - {__0} - - - {__0} - - - {__0} - - - {__0} - - - {__0} - - - {__0} - - - {__0} - - - {__0} - - + {__0} diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs index d66e4c660f7b5..400e8801ca217 100644 --- a/tests/debuginfo/msvc-pretty-enums.rs +++ b/tests/debuginfo/msvc-pretty-enums.rs @@ -46,12 +46,12 @@ // cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int] // cdb-command: dx niche128_some -// cdb-check: niche128_some : Some [Type: enum2$ >] +// cdb-check: niche128_some : Some [Type: enum2$ > >] // Note: we can't actually read the value of the field because CDB cannot handle 128 bit integers. -// cdb-check: [+0x000] __0 [...] [Type: core::num::nonzero::NonZeroI128] +// cdb-check: [+0x000] __0 [...] [Type: core::num::nonzero::NonZero] // cdb-command: dx niche128_none -// cdb-check: niche128_none : None [Type: enum2$ >] +// cdb-check: niche128_none : None [Type: enum2$ > >] // cdb-command: dx wrapping_niche128_untagged // cdb-check: wrapping_niche128_untagged : X [Type: enum2$] @@ -84,7 +84,7 @@ // cdb-command: dx niche_w_fields_2_some,d // cdb-check: niche_w_fields_2_some,d : A [Type: enum2$] -// cdb-check: [+0x[...]] __0 : 800 [Type: core::num::nonzero::NonZeroU32] +// cdb-check: [+0x[...]] __0 : 800 [Type: core::num::nonzero::NonZero] // cdb-check: [+0x[...]] __1 : 900 [Type: unsigned __int64] // cdb-command: dx niche_w_fields_2_none,d diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs index c122112e6c77a..a1b5ae792a16b 100644 --- a/tests/debuginfo/numeric-types.rs +++ b/tests/debuginfo/numeric-types.rs @@ -3,59 +3,59 @@ // min-gdb-version: 8.1 // ignore-windows-gnu // emit_debug_gdb_scripts is disabled on Windows -// Tests the visualizations for `NonZero{I,U}{8,16,32,64,128,size}`, `Wrapping` and +// Tests the visualizations for `NonZero`, `Wrapping` and // `Atomic{Bool,I8,I16,I32,I64,Isize,U8,U16,U32,U64,Usize}` located in `libcore.natvis`. // === CDB TESTS ================================================================================== // cdb-command: g // cdb-command: dx nz_i8 -// cdb-check:nz_i8 : 11 [Type: core::num::nonzero::NonZeroI8] -// cdb-check: [] [Type: core::num::nonzero::NonZeroI8] +// cdb-check:nz_i8 : 11 [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_i16 -// cdb-check:nz_i16 : 22 [Type: core::num::nonzero::NonZeroI16] -// cdb-check: [] [Type: core::num::nonzero::NonZeroI16] +// cdb-check:nz_i16 : 22 [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_i32 -// cdb-check:nz_i32 : 33 [Type: core::num::nonzero::NonZeroI32] -// cdb-check: [] [Type: core::num::nonzero::NonZeroI32] +// cdb-check:nz_i32 : 33 [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_i64 -// cdb-check:nz_i64 : 44 [Type: core::num::nonzero::NonZeroI64] -// cdb-check: [] [Type: core::num::nonzero::NonZeroI64] +// cdb-check:nz_i64 : 44 [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // 128-bit integers don't seem to work in CDB // cdb-command: dx nz_i128 -// cdb-check: [] [Type: core::num::nonzero::NonZeroI128] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_isize -// cdb-check:nz_isize : 66 [Type: core::num::nonzero::NonZeroIsize] -// cdb-check: [] [Type: core::num::nonzero::NonZeroIsize] +// cdb-check:nz_isize : 66 [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_u8 -// cdb-check:nz_u8 : 0x4d [Type: core::num::nonzero::NonZeroU8] -// cdb-check: [] [Type: core::num::nonzero::NonZeroU8] +// cdb-check:nz_u8 : 0x4d [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_u16 -// cdb-check:nz_u16 : 0x58 [Type: core::num::nonzero::NonZeroU16] -// cdb-check: [] [Type: core::num::nonzero::NonZeroU16] +// cdb-check:nz_u16 : 0x58 [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_u32 -// cdb-check:nz_u32 : 0x63 [Type: core::num::nonzero::NonZeroU32] -// cdb-check: [] [Type: core::num::nonzero::NonZeroU32] +// cdb-check:nz_u32 : 0x63 [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_u64 -// cdb-check:nz_u64 : 0x64 [Type: core::num::nonzero::NonZeroU64] -// cdb-check: [] [Type: core::num::nonzero::NonZeroU64] +// cdb-check:nz_u64 : 0x64 [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // 128-bit integers don't seem to work in CDB // cdb-command: dx nz_u128 -// cdb-check: [] [Type: core::num::nonzero::NonZeroU128] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_usize -// cdb-check:nz_usize : 0x7a [Type: core::num::nonzero::NonZeroUsize] -// cdb-check: [] [Type: core::num::nonzero::NonZeroUsize] +// cdb-check:nz_usize : 0x7a [Type: core::num::nonzero::NonZero] +// cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx w_i8 // cdb-check:w_i8 : 10 [Type: core::num::wrapping::Wrapping] diff --git a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff index cb623e83f5298..be7f9cd441210 100644 --- a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff +++ b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff @@ -4,7 +4,7 @@ fn adt_transmutes() -> () { let mut _0: (); let _1: u8; - let mut _2: std::option::Option; + let mut _2: std::option::Option>; let mut _4: std::num::Wrapping; let mut _6: std::num::Wrapping; let mut _8: Union32; @@ -37,7 +37,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = Option::::Some(const _); + _2 = Option::>::Some(const _); _1 = move _2 as u8 (Transmute); StorageDead(_2); StorageLive(_3); diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index 8161f97dde06c..0ed743818c573 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -232,7 +232,7 @@ error: layout_of(MultipleAlignments) = Layout { LL | enum MultipleAlignments { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: layout_of(Result<[u32; 0], Packed>) = Layout { +error: layout_of(Result<[u32; 0], Packed>>) = Layout { size: Size(4 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs index 09fda33dbec5c..9740742fbbb0f 100644 --- a/tests/ui/lint/clashing-extern-fn.rs +++ b/tests/ui/lint/clashing-extern-fn.rs @@ -436,7 +436,7 @@ mod hidden_niche { fn hidden_niche_unsafe_cell() -> Option>; //~^ WARN redeclared with a different signature - //~| WARN block uses type `Option>`, which is not FFI-safe + //~| WARN block uses type `Option>>`, which is not FFI-safe } } } diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr index 0d269e599dd1a..5b9244b699311 100644 --- a/tests/ui/lint/clashing-extern-fn.stderr +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -8,7 +8,7 @@ LL | fn hidden_niche_transparent_no_niche() -> Option>`, which is not FFI-safe +warning: `extern` block uses type `Option>>`, which is not FFI-safe --> $DIR/clashing-extern-fn.rs:437:46 | LL | fn hidden_niche_unsafe_cell() -> Option>; @@ -163,7 +163,7 @@ LL | fn non_zero_usize() -> core::num::NonZeroUsize; LL | fn non_zero_usize() -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | - = note: expected `unsafe extern "C" fn() -> NonZeroUsize` + = note: expected `unsafe extern "C" fn() -> NonZero` found `unsafe extern "C" fn() -> usize` warning: `non_null_ptr` redeclared with a different signature @@ -224,7 +224,7 @@ LL | fn hidden_niche_unsafe_cell() -> Option usize` - found `unsafe extern "C" fn() -> Option>` + found `unsafe extern "C" fn() -> Option>>` warning: 19 warnings emitted diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr index 57531b0968f1e..bdf47343114c6 100644 --- a/tests/ui/lint/invalid_value.stderr +++ b/tests/ui/lint/invalid_value.stderr @@ -316,7 +316,7 @@ LL | let _val: NonNull = mem::uninitialized(); = note: `std::ptr::NonNull` must be non-null = note: raw pointers must be initialized -error: the type `(NonZeroU32, i32)` does not permit zero-initialization +error: the type `(NonZero, i32)` does not permit zero-initialization --> $DIR/invalid_value.rs:95:39 | LL | let _val: (NonZeroU32, i32) = mem::zeroed(); @@ -325,9 +325,9 @@ LL | let _val: (NonZeroU32, i32) = mem::zeroed(); | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | - = note: `std::num::NonZeroU32` must be non-null + = note: `std::num::NonZero` must be non-null -error: the type `(NonZeroU32, i32)` does not permit being left uninitialized +error: the type `(NonZero, i32)` does not permit being left uninitialized --> $DIR/invalid_value.rs:96:39 | LL | let _val: (NonZeroU32, i32) = mem::uninitialized(); @@ -336,7 +336,7 @@ LL | let _val: (NonZeroU32, i32) = mem::uninitialized(); | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | - = note: `std::num::NonZeroU32` must be non-null + = note: `std::num::NonZero` must be non-null = note: integers must be initialized error: the type `*const dyn Send` does not permit zero-initialization @@ -417,7 +417,7 @@ LL | let _val: OneFruitNonZero = mem::zeroed(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `OneFruitNonZero` must be non-null -note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) +note: because `std::num::NonZero` must be non-null (in this field of the only potentially inhabited enum variant) --> $DIR/invalid_value.rs:39:12 | LL | Banana(NonZeroU32), @@ -433,7 +433,7 @@ LL | let _val: OneFruitNonZero = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `OneFruitNonZero` must be non-null -note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) +note: because `std::num::NonZero` must be non-null (in this field of the only potentially inhabited enum variant) --> $DIR/invalid_value.rs:39:12 | LL | Banana(NonZeroU32), @@ -603,7 +603,7 @@ LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); | = note: references must be non-null -error: the type `NonZeroU32` does not permit zero-initialization +error: the type `NonZero` does not permit zero-initialization --> $DIR/invalid_value.rs:154:32 | LL | let _val: NonZeroU32 = mem::transmute(0); @@ -612,7 +612,7 @@ LL | let _val: NonZeroU32 = mem::transmute(0); | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | - = note: `std::num::NonZeroU32` must be non-null + = note: `std::num::NonZero` must be non-null error: the type `NonNull` does not permit zero-initialization --> $DIR/invalid_value.rs:157:34 diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr index 8554e261778e7..64beefbb7579f 100644 --- a/tests/ui/lint/lint-ctypes-enum.stderr +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -61,7 +61,7 @@ LL | fn nonzero_i128(x: Option); | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `Option>`, which is not FFI-safe +error: `extern` block uses type `Option>>`, which is not FFI-safe --> $DIR/lint-ctypes-enum.rs:86:28 | LL | fn transparent_union(x: Option>); @@ -70,7 +70,7 @@ LL | fn transparent_union(x: Option>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint -error: `extern` block uses type `Option>`, which is not FFI-safe +error: `extern` block uses type `Option>>`, which is not FFI-safe --> $DIR/lint-ctypes-enum.rs:88:20 | LL | fn repr_rust(x: Option>); @@ -79,7 +79,7 @@ LL | fn repr_rust(x: Option>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint -error: `extern` block uses type `Result<(), NonZeroI32>`, which is not FFI-safe +error: `extern` block uses type `Result<(), NonZero>`, which is not FFI-safe --> $DIR/lint-ctypes-enum.rs:89:20 | LL | fn no_result(x: Result<(), num::NonZeroI32>); diff --git a/tests/ui/mismatched_types/non_zero_assigned_something.stderr b/tests/ui/mismatched_types/non_zero_assigned_something.stderr index 57db71f889cf7..f8e86905ab9bb 100644 --- a/tests/ui/mismatched_types/non_zero_assigned_something.stderr +++ b/tests/ui/mismatched_types/non_zero_assigned_something.stderr @@ -2,10 +2,12 @@ error[E0308]: mismatched types --> $DIR/non_zero_assigned_something.rs:2:35 | LL | let _: std::num::NonZeroU64 = 1; - | -------------------- ^ expected `NonZeroU64`, found integer + | -------------------- ^ expected `NonZero`, found integer | | | expected due to this | + = note: expected struct `NonZero` + found type `{integer}` help: consider calling `NonZeroU64::new` | LL | let _: std::num::NonZeroU64 = NonZeroU64::new(1).unwrap(); @@ -15,11 +17,11 @@ error[E0308]: mismatched types --> $DIR/non_zero_assigned_something.rs:6:43 | LL | let _: Option = 1; - | ---------------------------- ^ expected `Option`, found integer + | ---------------------------- ^ expected `Option>`, found integer | | | expected due to this | - = note: expected enum `Option` + = note: expected enum `Option>` found type `{integer}` help: consider calling `NonZeroU64::new` | diff --git a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr index e1825eb5b541d..be0fc0f98e24d 100644 --- a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr +++ b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -124,7 +124,7 @@ LL | x / 100.0 = help: the trait `Div<{float}>` is not implemented for `u8` = help: the following other types implement trait `Div`: - > + >> > <&'a u8 as Div> <&u8 as Div<&u8>> diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout index d1753c26ca83b..b53b893660321 100644 --- a/tests/ui/print_type_sizes/niche-filling.stdout +++ b/tests/ui/print_type_sizes/niche-filling.stdout @@ -14,17 +14,17 @@ print-type-size field `.pre`: 1 bytes print-type-size field `.post`: 2 bytes print-type-size field `.val`: 4 bytes print-type-size variant `None`: 0 bytes -print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size type: `MyOption>>`: 8 bytes, alignment: 4 bytes print-type-size discriminant: 4 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size variant `None`: 0 bytes -print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size type: `MyOption, std::num::NonZero>>`: 8 bytes, alignment: 4 bytes print-type-size discriminant: 4 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size variant `None`: 0 bytes -print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size type: `MyOption, u32>>`: 8 bytes, alignment: 4 bytes print-type-size discriminant: 4 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes @@ -53,22 +53,22 @@ print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size variant `None`: 0 bytes -print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes +print-type-size type: `MyOption>`: 4 bytes, alignment: 4 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size variant `None`: 0 bytes -print-type-size type: `Union1`: 4 bytes, alignment: 4 bytes +print-type-size type: `Union1>`: 4 bytes, alignment: 4 bytes print-type-size variant `Union1`: 4 bytes print-type-size field `.a`: 4 bytes -print-type-size type: `Union2`: 4 bytes, alignment: 4 bytes +print-type-size type: `Union2, std::num::NonZero>`: 4 bytes, alignment: 4 bytes print-type-size variant `Union2`: 4 bytes print-type-size field `.a`: 4 bytes print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes -print-type-size type: `Union2`: 4 bytes, alignment: 4 bytes +print-type-size type: `Union2, u32>`: 4 bytes, alignment: 4 bytes print-type-size variant `Union2`: 4 bytes print-type-size field `.a`: 4 bytes print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes -print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes +print-type-size type: `std::num::NonZero`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes print-type-size type: `Enum4<(), (), (), MyOption>`: 2 bytes, alignment: 1 bytes print-type-size variant `Four`: 2 bytes diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr index b130b7620fc0d..bffad037fba05 100644 --- a/tests/ui/traits/issue-77982.stderr +++ b/tests/ui/traits/issue-77982.stderr @@ -46,7 +46,7 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect( = note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate: - impl From for u32; - impl From for u32; - - impl From for u32; + - impl From> for u32; - impl From for u32; - impl From for u32; - impl From for u32; diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index 4d046635d6442..7e5b68353fb2d 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -11,7 +11,7 @@ LL | Ok(Err(123_i32)?) = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following other types implement trait `From`: > - > + >> > = note: required for `Result` to implement `FromResidual>` From b867c7c707be0070beac663a03eb6a797f076f68 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sat, 27 Jan 2024 08:47:14 -0800 Subject: [PATCH 300/676] Update primitive_docs.rs --- library/core/src/primitive_docs.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index fca2d3979ab47..e9c30ce9a23f5 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1392,10 +1392,8 @@ mod prim_usize {} /// /// # Safety /// -/// For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, unsafe code may assume that -/// the following properties hold. Rust programmers must assume that, unless explicitly stated -/// otherwise, any Rust code they did not author themselves may rely on these properties, and that -/// violating them may cause that code to exhibit undefined behavior. +/// For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, when such values cross an API +/// boundary, the following invariants must generally be upheld: /// /// * `t` is aligned to `align_of_val(t)` /// * `t` is dereferenceable for `size_of_val(t)` many bytes @@ -1403,9 +1401,16 @@ mod prim_usize {} /// If `t` points at address `a`, being "dereferenceable" for N bytes means that the memory range /// `[a, a + N)` is all contained within a single [allocated object]. /// -/// Note that the precise validity invariants for reference types are a work in progress. In the -/// future, new guarantees may be added. However, the guarantees documented in this section will -/// never be removed. +/// For instance, this means that unsafe code in a safe function may assume these invariants are +/// ensured of arguments passed by the caller, and it may assume that these invariants are ensured +/// of return values from any safe functions it calls. In most cases, the inverse is also true: +/// unsafe code must not violate these invariants when passing arguments to safe functions or +/// returning values from safe functions; such violations may result in undefined behavior. Where +/// exceptions to this latter requirement exist, they will be called out explicitly in documentation. +/// +/// It is not decided yet whether unsafe code may violate these invariants temporarily on internal +/// data. As a consequence, unsafe code which violates these invariants temporarily on internal data +/// may become unsound in future versions of Rust depending on how this question is decided. /// /// [allocated object]: ptr#allocated-object #[stable(feature = "rust1", since = "1.0.0")] From 2251e9abee68f1f8ad7b80938b2e36a96f7768c1 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 15 Jan 2024 11:28:13 +0000 Subject: [PATCH 301/676] Reject infinitely-sized reads from io::Repeat Related to #117925 --- library/std/src/io/util.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 6bc8f181c905f..a04bc4811460b 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -204,6 +204,16 @@ impl Read for Repeat { Ok(()) } + /// This function is not supported by `io::Repeat`, because there's no end of its data + fn read_to_end(&mut self, _: &mut Vec) -> io::Result { + Err(io::Error::from(io::ErrorKind::OutOfMemory)) + } + + /// This function is not supported by `io::Repeat`, because there's no end of its data + fn read_to_string(&mut self, _: &mut String) -> io::Result { + Err(io::Error::from(io::ErrorKind::OutOfMemory)) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let mut nwritten = 0; From 4c010259ef3c9eec239f5006dfdeffc73548cf07 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 27 Jan 2024 18:55:21 +0000 Subject: [PATCH 302/676] 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 5d8c1780fae725ce02a1c4619809347e55af67eb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 27 Jan 2024 00:50:31 +0000 Subject: [PATCH 303/676] Make the coroutine def id of an async closure the child of the closure def id --- compiler/rustc_resolve/src/def_collector.rs | 18 ++++++++++++------ .../ui/async-await/async-closures/def-path.rs | 14 ++++++++++++++ .../async-await/async-closures/def-path.stderr | 17 +++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 tests/ui/async-await/async-closures/def-path.rs create mode 100644 tests/ui/async-await/async-closures/def-path.stderr diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index b77102c085c59..42ace9bb22fa9 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -289,12 +289,18 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { // we must create two defs. let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span); match closure.coroutine_kind { - Some(coroutine_kind) => self.create_def( - coroutine_kind.closure_id(), - kw::Empty, - DefKind::Closure, - expr.span, - ), + Some(coroutine_kind) => { + self.with_parent(closure_def, |this| { + let coroutine_def = this.create_def( + coroutine_kind.closure_id(), + kw::Empty, + DefKind::Closure, + expr.span, + ); + this.with_parent(coroutine_def, |this| visit::walk_expr(this, expr)); + }); + return; + } None => closure_def, } } diff --git a/tests/ui/async-await/async-closures/def-path.rs b/tests/ui/async-await/async-closures/def-path.rs new file mode 100644 index 0000000000000..2883a1715b0ac --- /dev/null +++ b/tests/ui/async-await/async-closures/def-path.rs @@ -0,0 +1,14 @@ +// compile-flags: -Zverbose-internals +// edition:2021 + +#![feature(async_closure)] + +fn main() { + let x = async || {}; + //~^ NOTE the expected `async` closure body + let () = x(); + //~^ ERROR mismatched types + //~| NOTE this expression has type `{static main::{closure#0}::{closure#0} upvar_tys= + //~| NOTE expected `async` closure body, found `()` + //~| NOTE expected `async` closure body `{static main::{closure#0}::{closure#0} +} diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr new file mode 100644 index 0000000000000..4b37e50aac459 --- /dev/null +++ b/tests/ui/async-await/async-closures/def-path.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/def-path.rs:9:9 + | +LL | let x = async || {}; + | -- the expected `async` closure body +LL | +LL | let () = x(); + | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?7t witness=?8t}` + | | + | expected `async` closure body, found `()` + | + = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?7t witness=?8t}` + found unit type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 5f8030dcc9eaa68975279134d76c4a1eb941081b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 27 Jan 2024 17:46:50 +0300 Subject: [PATCH 304/676] hir: Remove unnecessary `HirId` from `hir::Let` It has 1-to-1 correspondence to its expression id. Also remove mostly useless `visit_let_expr`. --- compiler/rustc_ast_lowering/src/expr.rs | 1 - compiler/rustc_hir/src/hir.rs | 1 - compiler/rustc_hir/src/intravisit.rs | 18 ++++++------------ compiler/rustc_hir_typeck/src/expr.rs | 6 +++--- compiler/rustc_hir_typeck/src/gather_locals.rs | 14 ++++++++------ compiler/rustc_passes/src/hir_stats.rs | 5 ----- 6 files changed, 17 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index cc172b376573f..0ad4a59c17eb1 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -153,7 +153,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Let(pat, scrutinee, span, is_recovered) => { hir::ExprKind::Let(self.arena.alloc(hir::Let { - hir_id: self.next_id(), span: self.lower_span(*span), pat: self.lower_pat(pat), ty: None, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 23881cfd7dfd3..e34ea73952f5a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1273,7 +1273,6 @@ pub struct Arm<'hir> { /// desugaring to if-let. Only let-else supports the type annotation at present. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Let<'hir> { - pub hir_id: HirId, pub span: Span, pub pat: &'hir Pat<'hir>, pub ty: Option<&'hir Ty<'hir>>, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 116de6fb04d99..38ec325630b38 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -341,9 +341,6 @@ pub trait Visitor<'v>: Sized { fn visit_expr(&mut self, ex: &'v Expr<'v>) { walk_expr(self, ex) } - fn visit_let_expr(&mut self, lex: &'v Let<'v>) { - walk_let_expr(self, lex) - } fn visit_expr_field(&mut self, field: &'v ExprField<'v>) { walk_expr_field(self, field) } @@ -729,7 +726,12 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::DropTemps(ref subexpression) => { visitor.visit_expr(subexpression); } - ExprKind::Let(ref let_expr) => visitor.visit_let_expr(let_expr), + ExprKind::Let(Let { span: _, pat, ty, init, is_recovered: _ }) => { + // match the visit order in walk_local + visitor.visit_expr(init); + visitor.visit_pat(pat); + walk_list!(visitor, visit_ty, ty); + } ExprKind::If(ref cond, ref then, ref else_opt) => { visitor.visit_expr(cond); visitor.visit_expr(then); @@ -806,14 +808,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) } } -pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>) { - // match the visit order in walk_local - visitor.visit_expr(let_expr.init); - visitor.visit_id(let_expr.hir_id); - visitor.visit_pat(let_expr.pat); - walk_list!(visitor, visit_ty, let_expr.ty); -} - pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) { visitor.visit_id(field.hir_id); visitor.visit_ident(field.ident); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 3bc259c17b774..3bc4032558885 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -320,7 +320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), ExprKind::Become(call) => self.check_expr_become(call, expr), - ExprKind::Let(let_expr) => self.check_expr_let(let_expr), + ExprKind::Let(let_expr) => self.check_expr_let(let_expr, expr.hir_id), ExprKind::Loop(body, _, source, _) => { self.check_expr_loop(body, source, expected, expr) } @@ -1259,12 +1259,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(super) fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> { + pub(super) fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>, hir_id: HirId) -> Ty<'tcx> { // for let statements, this is done in check_stmt let init = let_expr.init; self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression"); // otherwise check exactly as a let statement - self.check_decl(let_expr.into()); + self.check_decl((let_expr, hir_id).into()); // but return a bool, for this is a boolean expression if let Some(error_guaranteed) = let_expr.is_recovered { self.set_tainted_by_errors(error_guaranteed); diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 52dc1e8591656..f9af357f0e79e 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -48,9 +48,9 @@ impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> { } } -impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> { - fn from(let_expr: &'a hir::Let<'a>) -> Self { - let hir::Let { hir_id, pat, ty, span, init, is_recovered: _ } = *let_expr; +impl<'a> From<(&'a hir::Let<'a>, hir::HirId)> for Declaration<'a> { + fn from((let_expr, hir_id): (&'a hir::Let<'a>, hir::HirId)) -> Self { + let hir::Let { pat, ty, span, init, is_recovered: _ } = *let_expr; Declaration { hir_id, pat, ty, span, init: Some(init), origin: DeclOrigin::LetExpr } } } @@ -125,9 +125,11 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { intravisit::walk_local(self, local) } - fn visit_let_expr(&mut self, let_expr: &'tcx hir::Let<'tcx>) { - self.declare(let_expr.into()); - intravisit::walk_let_expr(self, let_expr); + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + if let hir::ExprKind::Let(let_expr) = expr.kind { + self.declare((let_expr, expr.hir_id).into()); + } + intravisit::walk_expr(self, expr) } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 528a52f42255e..e94d8c4c932f9 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -328,11 +328,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_expr(self, e) } - fn visit_let_expr(&mut self, lex: &'v hir::Let<'v>) { - self.record("Let", Id::Node(lex.hir_id), lex); - hir_visit::walk_let_expr(self, lex) - } - fn visit_expr_field(&mut self, f: &'v hir::ExprField<'v>) { self.record("ExprField", Id::Node(f.hir_id), f); hir_visit::walk_expr_field(self, f) From b2b5b91bfbe5b39d17be3a14108fe7823627e0d8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 27 Jan 2024 18:59:20 +0300 Subject: [PATCH 305/676] hir: Use `InferArg` in `ArrayLen::Infer` --- compiler/rustc_ast_lowering/src/lib.rs | 5 ++++- compiler/rustc_hir/src/hir.rs | 8 +++++--- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_analysis/src/astconv/mod.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 4 ++-- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ee1f5d5bd7a3f..3621844efc8d2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2305,7 +2305,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match c.value.kind { ExprKind::Underscore => { if self.tcx.features().generic_arg_infer { - hir::ArrayLen::Infer(self.lower_node_id(c.id), self.lower_span(c.value.span)) + hir::ArrayLen::Infer(hir::InferArg { + hir_id: self.lower_node_id(c.id), + span: self.lower_span(c.value.span), + }) } else { feature_err( &self.tcx.sess, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e34ea73952f5a..681e228a0f2ff 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1531,14 +1531,16 @@ pub type Lit = Spanned; #[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum ArrayLen { - Infer(HirId, Span), + Infer(InferArg), Body(AnonConst), } impl ArrayLen { pub fn hir_id(&self) -> HirId { match self { - &ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, .. }) => hir_id, + ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(AnonConst { hir_id, .. }) => { + *hir_id + } } } } @@ -2423,7 +2425,7 @@ impl<'hir> Ty<'hir> { TyKind::Infer => true, TyKind::Slice(ty) => ty.is_suggestable_infer_ty(), TyKind::Array(ty, length) => { - ty.is_suggestable_infer_ty() || matches!(length, ArrayLen::Infer(_, _)) + ty.is_suggestable_infer_ty() || matches!(length, ArrayLen::Infer(..)) } TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty), TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 38ec325630b38..27c834d848fc4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -669,7 +669,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { match len { - &ArrayLen::Infer(hir_id, _span) => visitor.visit_id(hir_id), + ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), ArrayLen::Body(c) => visitor.visit_anon_const(c), } } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 7c97c2a1a6ff2..3ba63c659c776 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2529,7 +2529,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::Array(ty, length) => { let length = match length { - &hir::ArrayLen::Infer(_, span) => self.ct_infer(tcx.types.usize, None, span), + hir::ArrayLen::Infer(inf) => self.ct_infer(tcx.types.usize, None, inf.span), hir::ArrayLen::Body(constant) => { ty::Const::from_anon_const(tcx, constant.def_id) } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index d8ce2307995c5..8d862d5eb715f 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -146,8 +146,8 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector { } } fn visit_array_length(&mut self, length: &'v hir::ArrayLen) { - if let &hir::ArrayLen::Infer(_, span) = length { - self.0.push(span); + if let hir::ArrayLen::Infer(inf) = length { + self.0.push(inf.span); } intravisit::walk_array_len(self, length) } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index e76303bc6dfa1..9d0c5cb0f32b0 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -956,7 +956,7 @@ impl<'a> State<'a> { fn print_array_length(&mut self, len: &hir::ArrayLen) { match len { - hir::ArrayLen::Infer(_, _) => self.word("_"), + hir::ArrayLen::Infer(..) => self.word("_"), hir::ArrayLen::Body(ct) => self.print_anon_const(ct), } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c6b9197d0e986..e99489ee3c03c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -405,7 +405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> { match length { - &hir::ArrayLen::Infer(_, span) => self.ct_infer(self.tcx.types.usize, None, span), + hir::ArrayLen::Infer(inf) => self.ct_infer(self.tcx.types.usize, None, inf.span), hir::ArrayLen::Body(anon_const) => { let span = self.tcx.def_span(anon_const.def_id); let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8706abda97963..bc3c455f3980b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1835,7 +1835,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))), TyKind::Array(ty, ref length) => { let length = match length { - hir::ArrayLen::Infer(_, _) => "_".to_string(), + hir::ArrayLen::Infer(..) => "_".to_string(), hir::ArrayLen::Body(anon_const) => { // NOTE(min_const_generics): We can't use `const_eval_poly` for constants // as we currently do not supply the parent generics to anonymous constants From 9199742339b64dcc3aeaaf474156b593c93607fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 28 Jan 2024 02:02:50 +0100 Subject: [PATCH 306/676] Revert "Add the wasm32-wasi-preview2 target" This reverts commit 31ecf341250a889ac1154b2cbe3f0b97f9d008c1. Co-authored-by: Ryan Levick --- compiler/rustc_span/src/symbol.rs | 1 - compiler/rustc_target/src/spec/mod.rs | 1 - .../targets/wasm32_wasi_preview1_threads.rs | 3 +- .../src/spec/targets/wasm32_wasi_preview2.rs | 64 --------- library/std/src/os/mod.rs | 3 - library/std/src/os/wasi/mod.rs | 3 +- library/std/src/os/wasi_preview2/mod.rs | 5 - library/std/src/sys/pal/mod.rs | 3 - library/std/src/sys/pal/wasi/helpers.rs | 123 ---------------- library/std/src/sys/pal/wasi/mod.rs | 132 ++++++++++++++++-- library/std/src/sys/pal/wasi_preview2/mod.rs | 78 ----------- src/bootstrap/src/core/build_steps/compile.rs | 7 +- src/bootstrap/src/lib.rs | 2 +- src/doc/rustc/src/SUMMARY.md | 1 - src/doc/rustc/src/platform-support.md | 1 - .../platform-support/wasm32-wasi-preview2.md | 30 ---- tests/assembly/targets/targets-elf.rs | 3 - tests/ui/check-cfg/well-known-values.stderr | 4 +- 18 files changed, 130 insertions(+), 334 deletions(-) delete mode 100644 compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs delete mode 100644 library/std/src/os/wasi_preview2/mod.rs delete mode 100644 library/std/src/sys/pal/wasi/helpers.rs delete mode 100644 library/std/src/sys/pal/wasi_preview2/mod.rs delete mode 100644 src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 514d65abbe3e6..df5eed7eefe67 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1799,7 +1799,6 @@ symbols! { warn, wasm_abi, wasm_import_module, - wasm_preview2, wasm_target_feature, while_let, windows, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ead3be7fd529b..884bd23e8cce9 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1574,7 +1574,6 @@ supported_targets! { ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-wasi", wasm32_wasi), - ("wasm32-wasi-preview2", wasm32_wasi_preview2), ("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads), ("wasm64-unknown-unknown", wasm64_unknown_unknown), diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs index 389c67f8ae93b..28ea4cc9ece30 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs @@ -72,12 +72,11 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use crate::spec::{base, crt_objects, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; +use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; pub fn target() -> Target { let mut options = base::wasm::options(); - options.families = cvs!["wasm", "wasi"]; options.os = "wasi".into(); options.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs deleted file mode 100644 index fc44e5d4cbce9..0000000000000 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! The `wasm32-wasi-preview2` target is the next evolution of the -//! wasm32-wasi target. While the wasi specification is still under -//! active development, the {review 2 iteration is considered an "island -//! of stability" that should allow users to rely on it indefinitely. -//! -//! The `wasi` target is a proposal to define a standardized set of WebAssembly -//! component imports that allow it to interoperate with the host system in a -//! standardized way. This set of imports is intended to empower WebAssembly -//! binaries with host capabilities such as filesystem access, network access, etc. -//! -//! Wasi Preview 2 relies on the WebAssembly component model which is an extension of -//! the core WebAssembly specification which allows interoperability between WebAssembly -//! modules (known as "components") through high-level, shared-nothing APIs instead of the -//! low-level, shared-everything linear memory model of the core WebAssembly specification. -//! -//! You can see more about wasi at and the component model at -//! . - -use crate::spec::crt_objects; -use crate::spec::LinkSelfContainedDefault; -use crate::spec::{base, Target}; - -pub fn target() -> Target { - let mut options = base::wasm::options(); - - options.os = "wasi".into(); - options.env = "preview2".into(); - options.linker = Some("wasm-component-ld".into()); - - options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); - options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); - - // FIXME: Figure out cases in which WASM needs to link with a native toolchain. - options.link_self_contained = LinkSelfContainedDefault::True; - - // Right now this is a bit of a workaround but we're currently saying that - // the target by default has a static crt which we're taking as a signal - // for "use the bundled crt". If that's turned off then the system's crt - // will be used, but this means that default usage of this target doesn't - // need an external compiler but it's still interoperable with an external - // compiler if configured correctly. - options.crt_static_default = true; - options.crt_static_respected = true; - - // Allow `+crt-static` to create a "cdylib" output which is just a wasm file - // without a main function. - options.crt_static_allows_dylibs = true; - - // WASI's `sys::args::init` function ignores its arguments; instead, - // `args::args()` makes the WASI API calls itself. - options.main_needs_argc_argv = false; - - // And, WASI mangles the name of "main" to distinguish between different - // signatures. - options.entry_name = "__main_void".into(); - - Target { - llvm_target: "wasm32-unknown-unknown".into(), - pointer_width: 32, - data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(), - arch: "wasm32".into(), - options, - } -} diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index f03e079030503..6e11b92b618a3 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -85,9 +85,6 @@ pub mod linux; #[cfg(any(target_os = "wasi", doc))] pub mod wasi; -#[cfg(any(all(target_os = "wasi", target_env = "preview2"), doc))] -pub mod wasi_preview2; - // windows #[cfg(not(all( doc, diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index 05c8d30073f42..bbaf328f457e4 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -28,8 +28,7 @@ //! [`OsStr`]: crate::ffi::OsStr //! [`OsString`]: crate::ffi::OsString -#![cfg_attr(not(target_env = "preview2"), stable(feature = "rust1", since = "1.0.0"))] -#![cfg_attr(target_env = "preview2", unstable(feature = "wasm_preview2", issue = "none"))] +#![stable(feature = "rust1", since = "1.0.0")] #![deny(unsafe_op_in_unsafe_fn)] #![doc(cfg(target_os = "wasi"))] diff --git a/library/std/src/os/wasi_preview2/mod.rs b/library/std/src/os/wasi_preview2/mod.rs deleted file mode 100644 index 1d44dd72814b8..0000000000000 --- a/library/std/src/os/wasi_preview2/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Platform-specific extensions to `std` for Preview 2 of the WebAssembly System Interface (WASI). -//! -//! This module is currently empty, but will be filled over time as wasi-libc support for WASI Preview 2 is stabilized. - -#![stable(feature = "raw_ext", since = "1.1.0")] diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index f927d88d46c34..041b7c355822a 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -40,9 +40,6 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "wasi")] { mod wasi; pub use self::wasi::*; - } else if #[cfg(all(target_os = "wasi", target_env = "preview2"))] { - mod wasi_preview2; - pub use self::wasi_preview2::*; } else if #[cfg(target_family = "wasm")] { mod wasm; pub use self::wasm::*; diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs deleted file mode 100644 index 82149cef8fad1..0000000000000 --- a/library/std/src/sys/pal/wasi/helpers.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::io as std_io; -use crate::mem; - -#[inline] -pub fn is_interrupted(errno: i32) -> bool { - errno == wasi::ERRNO_INTR.raw().into() -} - -pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { - use std_io::ErrorKind; - - let Ok(errno) = u16::try_from(errno) else { - return ErrorKind::Uncategorized; - }; - - macro_rules! match_errno { - ($($($errno:ident)|+ => $errkind:ident),*, _ => $wildcard:ident $(,)?) => { - match errno { - $(e if $(e == ::wasi::$errno.raw())||+ => ErrorKind::$errkind),*, - _ => ErrorKind::$wildcard, - } - }; - } - - match_errno! { - ERRNO_2BIG => ArgumentListTooLong, - ERRNO_ACCES => PermissionDenied, - ERRNO_ADDRINUSE => AddrInUse, - ERRNO_ADDRNOTAVAIL => AddrNotAvailable, - ERRNO_AFNOSUPPORT => Unsupported, - ERRNO_AGAIN => WouldBlock, - // ALREADY => "connection already in progress", - // BADF => "bad file descriptor", - // BADMSG => "bad message", - ERRNO_BUSY => ResourceBusy, - // CANCELED => "operation canceled", - // CHILD => "no child processes", - ERRNO_CONNABORTED => ConnectionAborted, - ERRNO_CONNREFUSED => ConnectionRefused, - ERRNO_CONNRESET => ConnectionReset, - ERRNO_DEADLK => Deadlock, - // DESTADDRREQ => "destination address required", - ERRNO_DOM => InvalidInput, - // DQUOT => /* reserved */, - ERRNO_EXIST => AlreadyExists, - // FAULT => "bad address", - ERRNO_FBIG => FileTooLarge, - ERRNO_HOSTUNREACH => HostUnreachable, - // IDRM => "identifier removed", - // ILSEQ => "illegal byte sequence", - // INPROGRESS => "operation in progress", - ERRNO_INTR => Interrupted, - ERRNO_INVAL => InvalidInput, - ERRNO_IO => Uncategorized, - // ISCONN => "socket is connected", - ERRNO_ISDIR => IsADirectory, - ERRNO_LOOP => FilesystemLoop, - // MFILE => "file descriptor value too large", - ERRNO_MLINK => TooManyLinks, - // MSGSIZE => "message too large", - // MULTIHOP => /* reserved */, - ERRNO_NAMETOOLONG => InvalidFilename, - ERRNO_NETDOWN => NetworkDown, - // NETRESET => "connection aborted by network", - ERRNO_NETUNREACH => NetworkUnreachable, - // NFILE => "too many files open in system", - // NOBUFS => "no buffer space available", - ERRNO_NODEV => NotFound, - ERRNO_NOENT => NotFound, - // NOEXEC => "executable file format error", - // NOLCK => "no locks available", - // NOLINK => /* reserved */, - ERRNO_NOMEM => OutOfMemory, - // NOMSG => "no message of the desired type", - // NOPROTOOPT => "protocol not available", - ERRNO_NOSPC => StorageFull, - ERRNO_NOSYS => Unsupported, - ERRNO_NOTCONN => NotConnected, - ERRNO_NOTDIR => NotADirectory, - ERRNO_NOTEMPTY => DirectoryNotEmpty, - // NOTRECOVERABLE => "state not recoverable", - // NOTSOCK => "not a socket", - ERRNO_NOTSUP => Unsupported, - // NOTTY => "inappropriate I/O control operation", - ERRNO_NXIO => NotFound, - // OVERFLOW => "value too large to be stored in data type", - // OWNERDEAD => "previous owner died", - ERRNO_PERM => PermissionDenied, - ERRNO_PIPE => BrokenPipe, - // PROTO => "protocol error", - ERRNO_PROTONOSUPPORT => Unsupported, - // PROTOTYPE => "protocol wrong type for socket", - // RANGE => "result too large", - ERRNO_ROFS => ReadOnlyFilesystem, - ERRNO_SPIPE => NotSeekable, - ERRNO_SRCH => NotFound, - // STALE => /* reserved */, - ERRNO_TIMEDOUT => TimedOut, - ERRNO_TXTBSY => ResourceBusy, - ERRNO_XDEV => CrossesDevices, - ERRNO_NOTCAPABLE => PermissionDenied, - _ => Uncategorized, - } -} - -pub fn abort_internal() -> ! { - unsafe { libc::abort() } -} - -pub fn hashmap_random_keys() -> (u64, u64) { - let mut ret = (0u64, 0u64); - unsafe { - let base = &mut ret as *mut (u64, u64) as *mut u8; - let len = mem::size_of_val(&ret); - wasi::random_get(base, len).expect("random_get failure"); - } - return ret; -} - -#[inline] -pub(crate) fn err2io(err: wasi::Errno) -> std_io::Error { - std_io::Error::from_raw_os_error(err.raw().into()) -} diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index a4b55093bf47f..4ffc8ecdd67ee 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -14,6 +14,9 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! +use crate::io as std_io; +use crate::mem; + #[path = "../unix/alloc.rs"] pub mod alloc; pub mod args; @@ -69,12 +72,123 @@ cfg_if::cfg_if! { mod common; pub use common::*; -mod helpers; -// These exports are listed individually to work around Rust's glob import -// conflict rules. If we glob export `helpers` and `common` together, then -// the compiler complains about conflicts. -pub use helpers::abort_internal; -pub use helpers::decode_error_kind; -use helpers::err2io; -pub use helpers::hashmap_random_keys; -pub use helpers::is_interrupted; +#[inline] +pub fn is_interrupted(errno: i32) -> bool { + errno == wasi::ERRNO_INTR.raw().into() +} + +pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { + use std_io::ErrorKind; + + let Ok(errno) = u16::try_from(errno) else { + return ErrorKind::Uncategorized; + }; + + macro_rules! match_errno { + ($($($errno:ident)|+ => $errkind:ident),*, _ => $wildcard:ident $(,)?) => { + match errno { + $(e if $(e == ::wasi::$errno.raw())||+ => ErrorKind::$errkind),*, + _ => ErrorKind::$wildcard, + } + }; + } + + match_errno! { + ERRNO_2BIG => ArgumentListTooLong, + ERRNO_ACCES => PermissionDenied, + ERRNO_ADDRINUSE => AddrInUse, + ERRNO_ADDRNOTAVAIL => AddrNotAvailable, + ERRNO_AFNOSUPPORT => Unsupported, + ERRNO_AGAIN => WouldBlock, + // ALREADY => "connection already in progress", + // BADF => "bad file descriptor", + // BADMSG => "bad message", + ERRNO_BUSY => ResourceBusy, + // CANCELED => "operation canceled", + // CHILD => "no child processes", + ERRNO_CONNABORTED => ConnectionAborted, + ERRNO_CONNREFUSED => ConnectionRefused, + ERRNO_CONNRESET => ConnectionReset, + ERRNO_DEADLK => Deadlock, + // DESTADDRREQ => "destination address required", + ERRNO_DOM => InvalidInput, + // DQUOT => /* reserved */, + ERRNO_EXIST => AlreadyExists, + // FAULT => "bad address", + ERRNO_FBIG => FileTooLarge, + ERRNO_HOSTUNREACH => HostUnreachable, + // IDRM => "identifier removed", + // ILSEQ => "illegal byte sequence", + // INPROGRESS => "operation in progress", + ERRNO_INTR => Interrupted, + ERRNO_INVAL => InvalidInput, + ERRNO_IO => Uncategorized, + // ISCONN => "socket is connected", + ERRNO_ISDIR => IsADirectory, + ERRNO_LOOP => FilesystemLoop, + // MFILE => "file descriptor value too large", + ERRNO_MLINK => TooManyLinks, + // MSGSIZE => "message too large", + // MULTIHOP => /* reserved */, + ERRNO_NAMETOOLONG => InvalidFilename, + ERRNO_NETDOWN => NetworkDown, + // NETRESET => "connection aborted by network", + ERRNO_NETUNREACH => NetworkUnreachable, + // NFILE => "too many files open in system", + // NOBUFS => "no buffer space available", + ERRNO_NODEV => NotFound, + ERRNO_NOENT => NotFound, + // NOEXEC => "executable file format error", + // NOLCK => "no locks available", + // NOLINK => /* reserved */, + ERRNO_NOMEM => OutOfMemory, + // NOMSG => "no message of the desired type", + // NOPROTOOPT => "protocol not available", + ERRNO_NOSPC => StorageFull, + ERRNO_NOSYS => Unsupported, + ERRNO_NOTCONN => NotConnected, + ERRNO_NOTDIR => NotADirectory, + ERRNO_NOTEMPTY => DirectoryNotEmpty, + // NOTRECOVERABLE => "state not recoverable", + // NOTSOCK => "not a socket", + ERRNO_NOTSUP => Unsupported, + // NOTTY => "inappropriate I/O control operation", + ERRNO_NXIO => NotFound, + // OVERFLOW => "value too large to be stored in data type", + // OWNERDEAD => "previous owner died", + ERRNO_PERM => PermissionDenied, + ERRNO_PIPE => BrokenPipe, + // PROTO => "protocol error", + ERRNO_PROTONOSUPPORT => Unsupported, + // PROTOTYPE => "protocol wrong type for socket", + // RANGE => "result too large", + ERRNO_ROFS => ReadOnlyFilesystem, + ERRNO_SPIPE => NotSeekable, + ERRNO_SRCH => NotFound, + // STALE => /* reserved */, + ERRNO_TIMEDOUT => TimedOut, + ERRNO_TXTBSY => ResourceBusy, + ERRNO_XDEV => CrossesDevices, + ERRNO_NOTCAPABLE => PermissionDenied, + _ => Uncategorized, + } +} + +pub fn abort_internal() -> ! { + unsafe { libc::abort() } +} + +pub fn hashmap_random_keys() -> (u64, u64) { + let mut ret = (0u64, 0u64); + unsafe { + let base = &mut ret as *mut (u64, u64) as *mut u8; + let len = mem::size_of_val(&ret); + wasi::random_get(base, len).expect("random_get failure"); + } + return ret; +} + +#[inline] +fn err2io(err: wasi::Errno) -> std_io::Error { + std_io::Error::from_raw_os_error(err.raw().into()) +} diff --git a/library/std/src/sys/pal/wasi_preview2/mod.rs b/library/std/src/sys/pal/wasi_preview2/mod.rs deleted file mode 100644 index b61695015bbd9..0000000000000 --- a/library/std/src/sys/pal/wasi_preview2/mod.rs +++ /dev/null @@ -1,78 +0,0 @@ -//! System bindings for the wasi preview 2 target. -//! -//! This is the next evolution of the original wasi target, and is intended to -//! replace that target over time. -//! -//! To begin with, this target mirrors the wasi target 1 to 1, but over -//! time this will change significantly. - -#[path = "../unix/alloc.rs"] -pub mod alloc; -#[path = "../wasi/args.rs"] -pub mod args; -#[path = "../unix/cmath.rs"] -pub mod cmath; -#[path = "../wasi/env.rs"] -pub mod env; -#[path = "../wasi/fd.rs"] -pub mod fd; -#[path = "../wasi/fs.rs"] -pub mod fs; -#[allow(unused)] -#[path = "../wasm/atomics/futex.rs"] -pub mod futex; -#[path = "../wasi/io.rs"] -pub mod io; - -#[path = "../wasi/net.rs"] -pub mod net; -#[path = "../wasi/os.rs"] -pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; -#[path = "../unix/path.rs"] -pub mod path; -#[path = "../unsupported/pipe.rs"] -pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; -#[path = "../wasi/stdio.rs"] -pub mod stdio; -#[path = "../wasi/thread.rs"] -pub mod thread; -#[path = "../unsupported/thread_local_dtor.rs"] -pub mod thread_local_dtor; -#[path = "../unsupported/thread_local_key.rs"] -pub mod thread_local_key; -#[path = "../wasi/time.rs"] -pub mod time; - -cfg_if::cfg_if! { - if #[cfg(target_feature = "atomics")] { - compile_error!("The wasm32-wasi-preview2 target does not support atomics"); - } else { - #[path = "../unsupported/locks/mod.rs"] - pub mod locks; - #[path = "../unsupported/once.rs"] - pub mod once; - #[path = "../unsupported/thread_parking.rs"] - pub mod thread_parking; - } -} - -#[path = "../unsupported/common.rs"] -#[deny(unsafe_op_in_unsafe_fn)] -#[allow(unused)] -mod common; -pub use common::*; - -#[path = "../wasi/helpers.rs"] -mod helpers; -// These exports are listed individually to work around Rust's glob import -// conflict rules. If we glob export `helpers` and `common` together, then -// the compiler complains about conflicts. -pub use helpers::abort_internal; -pub use helpers::decode_error_kind; -use helpers::err2io; -pub use helpers::hashmap_random_keys; -pub use helpers::is_interrupted; diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 043473287fcf8..ddbe18ab8388d 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -367,13 +367,10 @@ fn copy_self_contained_objects( let srcdir = builder .wasi_root(target) .unwrap_or_else(|| { - panic!( - "Target {:?} does not have a \"wasi-root\" key in Config.toml", - target.triple - ) + panic!("Target {:?} does not have a \"wasi-root\" key", target.triple) }) .join("lib") - .join(target.to_string().replace("-preview1", "").replace("-preview2", "")); + .join(target.to_string().replace("-preview1", "")); for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] { copy_and_stamp( builder, diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 1726e7aacbcea..1336abf6c7aba 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -88,7 +88,7 @@ const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ (Some(Mode::Std), "no_sync", None), (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ - (Some(Mode::Std), "target_env", Some(&["libnx", "preview2"])), + (Some(Mode::Std), "target_env", Some(&["libnx"])), // (Some(Mode::Std), "target_os", Some(&[])), // #[cfg(bootstrap)] zkvm (Some(Mode::Std), "target_os", Some(&["zkvm"])), diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 990998ea70431..1998b008dc811 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -59,7 +59,6 @@ - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md) - - [wasm32-wasi-preview2](platform-support/wasm32-wasi-preview2.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index fb751b7229eb4..f648a60b6c48d 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -360,7 +360,6 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL -[`wasm32-wasi-preview2`](platform-support/wasm32-wasi-preview2.md) | ✓ | | WebAssembly [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md b/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md deleted file mode 100644 index 837efd13d417e..0000000000000 --- a/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md +++ /dev/null @@ -1,30 +0,0 @@ -# `wasm32-wasi-preview2` - -**Tier: 3** - -The `wasm32-wasi-preview2` target is a new and still (as of January 2024) an -experimental target. This target is an extension to `wasm32-wasi-preview1` target, -originally known as `wasm32-wasi`. It is the next evolution in the development of -wasi (the [WebAssembly System Interface](https://wasi.dev)) that uses the WebAssembly -[component model] to allow for a standardized set of syscalls that are intended to empower -WebAssembly binaries with native host capabilities. - -[component model]: https://github.com/WebAssembly/component-model - -## Target maintainers - -- Alex Crichton, https://github.com/alexcrichton -- Ryan Levick, https://github.com/rylev - -## Requirements - -This target is cross-compiled. The target supports `std` fully. - -## Platform requirements - -The WebAssembly runtime should support the wasi preview 2 API set. - -This target is not a stable target. This means that there are only a few engines -which implement wasi preview 2, for example: - -* Wasmtime - `-W component-model` diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index dee0fa9f4a410..41f5df0fba001 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -489,9 +489,6 @@ // revisions: wasm64_unknown_unknown // [wasm64_unknown_unknown] compile-flags: --target wasm64-unknown-unknown // [wasm64_unknown_unknown] needs-llvm-components: webassembly -// revisions: wasm32_wasi_preview2 -// [wasm32_wasi_preview2] compile-flags: --target wasm32-wasi-preview2 -// [wasm32_wasi_preview2] needs-llvm-components: webassembly // revisions: x86_64_fortanix_unknown_sgx // [x86_64_fortanix_unknown_sgx] compile-flags: --target x86_64-fortanix-unknown-sgx // [x86_64_fortanix_unknown_sgx] needs-llvm-components: x86 diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index d7d538c0b9e3e..814d473619777 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -125,7 +125,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `preview2`, `psx`, `relibc`, `sgx`, `uclibc` + = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `psx`, `relibc`, `sgx`, `uclibc` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -134,7 +134,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_family` are: `unix`, `wasi`, `wasm`, `windows` + = note: expected values for `target_family` are: `unix`, `wasm`, `windows` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From 8fab92feb270f1725f25dc3b7529f8d3555eb404 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 20 Jan 2024 15:37:46 +0300 Subject: [PATCH 307/676] 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 308/676] 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 309/676] 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 310/676] 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 311/676] 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 312/676] 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 313/676] 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 314/676] 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 76689539eec27faae941f5419983a0ebad93aad7 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 20 Jan 2024 11:33:00 +0300 Subject: [PATCH 315/676] add more unit tests Signed-off-by: onur-ozkan --- src/bootstrap/src/tests/change_tracker.rs | 10 +++++ src/bootstrap/src/tests/helpers.rs | 48 ++++++++++++++++++++++- src/bootstrap/src/utils/change_tracker.rs | 4 ++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/bootstrap/src/tests/change_tracker.rs diff --git a/src/bootstrap/src/tests/change_tracker.rs b/src/bootstrap/src/tests/change_tracker.rs new file mode 100644 index 0000000000000..d2bfc07d1727b --- /dev/null +++ b/src/bootstrap/src/tests/change_tracker.rs @@ -0,0 +1,10 @@ +use crate::{find_recent_config_change_ids, CONFIG_CHANGE_HISTORY}; + +#[test] +fn test_find_recent_config_change_ids() { + // If change-id is greater than the most recent one, result should be empty. + assert!(find_recent_config_change_ids(usize::MAX).is_empty()); + + // There is no change-id equal to or less than 0, result should include the entire change history. + assert_eq!(find_recent_config_change_ids(0).len(), CONFIG_CHANGE_HISTORY.len()); +} diff --git a/src/bootstrap/src/tests/helpers.rs b/src/bootstrap/src/tests/helpers.rs index 2d626fad417d7..9cfaa3eb67b5c 100644 --- a/src/bootstrap/src/tests/helpers.rs +++ b/src/bootstrap/src/tests/helpers.rs @@ -1,5 +1,14 @@ -use crate::utils::helpers::{check_cfg_arg, extract_beta_rev, hex_encode, make}; -use std::path::PathBuf; +use crate::{ + utils::helpers::{ + check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, symlink_dir, + }, + Config, +}; +use std::{ + fs::{self, remove_file, File}, + io::Write, + path::PathBuf, +}; #[test] fn test_make() { @@ -70,3 +79,38 @@ fn test_check_cfg_arg() { "--check-cfg=cfg(target_os,values(\"nixos\",\"nix2\"))" ); } + +#[test] +fn test_program_out_of_date() { + let config = Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]); + let tempfile = config.tempdir().join(".tmp-stamp-file"); + File::create(&tempfile).unwrap().write_all(b"dummy value").unwrap(); + assert!(tempfile.exists()); + + // up-to-date + assert!(!program_out_of_date(&tempfile, "dummy value")); + // out-of-date + assert!(program_out_of_date(&tempfile, "")); + + remove_file(tempfile).unwrap(); +} + +#[test] +fn test_symlink_dir() { + let config = Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]); + let tempdir = config.tempdir().join(".tmp-dir"); + let link_path = config.tempdir().join(".tmp-link"); + + fs::create_dir_all(&tempdir).unwrap(); + symlink_dir(&config, &tempdir, &link_path).unwrap(); + + let link_source = fs::read_link(&link_path).unwrap(); + assert_eq!(link_source, tempdir); + + fs::remove_dir(tempdir).unwrap(); + + #[cfg(windows)] + fs::remove_dir(link_path).unwrap(); + #[cfg(not(windows))] + fs::remove_file(link_path).unwrap(); +} diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 327b4674acfdb..26d36ab52aba2 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -2,6 +2,10 @@ //! with the goal of keeping developers synchronized with important modifications in //! the bootstrap. +#[cfg(test)] +#[path = "../tests/change_tracker.rs"] +mod tests; + #[derive(Clone, Debug)] pub struct ChangeInfo { /// Represents the ID of PR caused major change on bootstrap. From d6a974d09643200377af60f6cfcf8cfad913721d Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 21 Jan 2024 10:47:12 +0300 Subject: [PATCH 316/676] bootstrap: update test modules Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/setup.rs | 1 - .../src/{tests/setup.rs => core/build_steps/setup/tests.rs} | 0 src/bootstrap/src/core/builder.rs | 1 - .../src/{tests/builder.rs => core/builder/tests.rs} | 0 src/bootstrap/src/core/config/config.rs | 6 +----- src/bootstrap/src/core/config/mod.rs | 2 ++ src/bootstrap/src/{tests/config.rs => core/config/tests.rs} | 2 +- src/bootstrap/src/utils/change_tracker.rs | 1 - .../change_tracker.rs => utils/change_tracker/tests.rs} | 0 src/bootstrap/src/utils/helpers.rs | 1 - .../src/{tests/helpers.rs => utils/helpers/tests.rs} | 0 11 files changed, 4 insertions(+), 10 deletions(-) rename src/bootstrap/src/{tests/setup.rs => core/build_steps/setup/tests.rs} (100%) rename src/bootstrap/src/{tests/builder.rs => core/builder/tests.rs} (100%) rename src/bootstrap/src/{tests/config.rs => core/config/tests.rs} (99%) rename src/bootstrap/src/{tests/change_tracker.rs => utils/change_tracker/tests.rs} (100%) rename src/bootstrap/src/{tests/helpers.rs => utils/helpers/tests.rs} (100%) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 9c897ae1bb784..8e3c9e2be8b85 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -14,7 +14,6 @@ use std::str::FromStr; use std::{fmt, fs, io}; #[cfg(test)] -#[path = "../../tests/setup.rs"] mod tests; #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] diff --git a/src/bootstrap/src/tests/setup.rs b/src/bootstrap/src/core/build_steps/setup/tests.rs similarity index 100% rename from src/bootstrap/src/tests/setup.rs rename to src/bootstrap/src/core/build_steps/setup/tests.rs diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 4e20babc55a68..a6b51f6ec63cf 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -32,7 +32,6 @@ use clap::ValueEnum; use once_cell::sync::Lazy; #[cfg(test)] -#[path = "../tests/builder.rs"] mod tests; pub struct Builder<'a> { diff --git a/src/bootstrap/src/tests/builder.rs b/src/bootstrap/src/core/builder/tests.rs similarity index 100% rename from src/bootstrap/src/tests/builder.rs rename to src/bootstrap/src/core/builder/tests.rs diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index fcdd742e69c22..c0dd1e1208484 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -3,10 +3,6 @@ //! This module implements parsing `config.toml` configuration files to tweak //! how the build runs. -#[cfg(test)] -#[path = "../../tests/config.rs"] -mod tests; - use std::cell::{Cell, RefCell}; use std::cmp; use std::collections::{HashMap, HashSet}; @@ -1203,7 +1199,7 @@ impl Config { Self::parse_inner(args, get_toml) } - fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config { + pub(crate) fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config { let mut flags = Flags::parse(&args); let mut config = Config::default_opts(); diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index 9c6861826d605..99412848abbb7 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -1,4 +1,6 @@ pub(crate) mod config; pub(crate) mod flags; +#[cfg(test)] +mod tests; pub use config::*; diff --git a/src/bootstrap/src/tests/config.rs b/src/bootstrap/src/core/config/tests.rs similarity index 99% rename from src/bootstrap/src/tests/config.rs rename to src/bootstrap/src/core/config/tests.rs index c65067f8e8f76..201d11571c48a 100644 --- a/src/bootstrap/src/tests/config.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -1,4 +1,4 @@ -use super::{Config, Flags}; +use super::{flags::Flags, Config}; use crate::core::config::{LldMode, TomlConfig}; use clap::CommandFactory; diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 26d36ab52aba2..0d5e2600b73a9 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -3,7 +3,6 @@ //! the bootstrap. #[cfg(test)] -#[path = "../tests/change_tracker.rs"] mod tests; #[derive(Clone, Debug)] diff --git a/src/bootstrap/src/tests/change_tracker.rs b/src/bootstrap/src/utils/change_tracker/tests.rs similarity index 100% rename from src/bootstrap/src/tests/change_tracker.rs rename to src/bootstrap/src/utils/change_tracker/tests.rs diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 0c917c3d57933..d1f713af91709 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -21,7 +21,6 @@ use crate::LldMode; pub use crate::utils::dylib::{dylib_path, dylib_path_var}; #[cfg(test)] -#[path = "../tests/helpers.rs"] mod tests; /// A helper macro to `unwrap` a result except also print out details like: diff --git a/src/bootstrap/src/tests/helpers.rs b/src/bootstrap/src/utils/helpers/tests.rs similarity index 100% rename from src/bootstrap/src/tests/helpers.rs rename to src/bootstrap/src/utils/helpers/tests.rs 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 317/676] 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 6f014a81b2466c2abdae4c06ff81fae7e1bc006c Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Sun, 28 Jan 2024 16:12:21 +0100 Subject: [PATCH 318/676] Handle methodcalls & operators in patterns --- compiler/rustc_parse/messages.ftl | 14 ++ compiler/rustc_parse/src/errors.rs | 12 ++ compiler/rustc_parse/src/parser/expr.rs | 13 ++ compiler/rustc_parse/src/parser/mod.rs | 1 + compiler/rustc_parse/src/parser/pat.rs | 155 ++++++++++++++++-- .../range_pat_interactions1.rs | 8 +- .../range_pat_interactions1.stderr | 73 ++++++++- .../range_pat_interactions2.rs | 8 +- .../range_pat_interactions2.stderr | 75 ++++++++- tests/ui/parser/issues/issue-24197.rs | 2 +- tests/ui/parser/issues/issue-24197.stderr | 6 +- tests/ui/parser/issues/issue-24375.rs | 2 +- tests/ui/parser/issues/issue-24375.stderr | 6 +- tests/ui/parser/pat-lt-bracket-5.rs | 4 +- tests/ui/parser/pat-lt-bracket-5.stderr | 15 +- tests/ui/parser/pat-lt-bracket-6.rs | 3 +- tests/ui/parser/pat-lt-bracket-6.stderr | 30 +++- tests/ui/parser/pat-ranges-3.rs | 6 +- tests/ui/parser/pat-ranges-3.stderr | 14 +- tests/ui/parser/pat-ranges-4.rs | 6 - tests/ui/parser/pat-ranges-4.stderr | 8 - tests/ui/parser/pat-recover-exprs.rs | 28 ++++ tests/ui/parser/pat-recover-exprs.stderr | 76 +++++++++ tests/ui/parser/pat-recover-methodcalls.rs | 37 +++++ .../ui/parser/pat-recover-methodcalls.stderr | 35 ++++ tests/ui/parser/pat-recover-ranges.rs | 16 ++ tests/ui/parser/pat-recover-ranges.stderr | 84 +++++++++- tests/ui/parser/pat-recover-wildcards.rs | 61 +++++++ tests/ui/parser/pat-recover-wildcards.stderr | 77 +++++++++ 29 files changed, 809 insertions(+), 66 deletions(-) delete mode 100644 tests/ui/parser/pat-ranges-4.rs delete mode 100644 tests/ui/parser/pat-ranges-4.stderr create mode 100644 tests/ui/parser/pat-recover-exprs.rs create mode 100644 tests/ui/parser/pat-recover-exprs.stderr create mode 100644 tests/ui/parser/pat-recover-methodcalls.rs create mode 100644 tests/ui/parser/pat-recover-methodcalls.stderr create mode 100644 tests/ui/parser/pat-recover-wildcards.rs create mode 100644 tests/ui/parser/pat-recover-wildcards.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index f904e0c44ea92..aac8c0b310320 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -772,6 +772,20 @@ parse_unexpected_const_param_declaration = unexpected `const` parameter declarat parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter .label = lifetime parameters cannot have default values +parse_unexpected_expr_in_pat = + expected {$is_bound -> + [true] a pattern range bound + *[false] a pattern + }, found {$is_method_call -> + [true] a method call + *[false] an expression + } + + .label = {$is_method_call -> + [true] method calls + *[false] arbitrary expressions + } are not allowed in patterns + parse_unexpected_if_with_if = unexpected `if` in the condition expression .suggestion = remove the `if` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 40852048293a9..fa91b64d5310d 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2415,6 +2415,18 @@ pub(crate) struct ExpectedCommaAfterPatternField { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parse_unexpected_expr_in_pat)] +pub(crate) struct UnexpectedExpressionInPattern { + #[primary_span] + #[label] + pub span: Span, + /// Was a `RangePatternBound` expected? + pub is_bound: bool, + /// Was the unexpected expression a `MethodCallExpression`? + pub is_method_call: bool, +} + #[derive(Diagnostic)] #[diag(parse_unexpected_paren_in_range_pat)] pub(crate) struct UnexpectedParenInRangePat { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b789b65797bad..c395decab129e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -444,6 +444,19 @@ impl<'a> Parser<'a> { ) if self.restrictions.contains(Restrictions::CONST_EXPR) => { return None; } + // When recovering patterns as expressions, stop parsing when encountering an assignment `=`, an alternative `|`, or a range `..`. + ( + Some( + AssocOp::Assign + | AssocOp::AssignOp(_) + | AssocOp::BitOr + | AssocOp::DotDot + | AssocOp::DotDotEq, + ), + _, + ) if self.restrictions.contains(Restrictions::IS_PAT) => { + return None; + } (Some(op), _) => (op, self.token.span), (None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => { self.dcx().emit_err(errors::InvalidLogicalOperator { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ff2fb6271a8df..623407eb38003 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -53,6 +53,7 @@ bitflags::bitflags! { const CONST_EXPR = 1 << 2; const ALLOW_LET = 1 << 3; const IN_IF_GUARD = 1 << 4; + const IS_PAT = 1 << 5; } } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 7918e03750ce3..d04921dde54b7 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,4 +1,4 @@ -use super::{ForceCollect, Parser, PathStyle, TrailingToken}; +use super::{ForceCollect, Parser, PathStyle, Restrictions, TrailingToken}; use crate::errors::{ self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, @@ -6,14 +6,14 @@ use crate::errors::{ InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, - TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, - UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, - UnexpectedVertVertInPattern, + TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern, + UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, + UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, }; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter}; +use rustc_ast::token::{self, BinOpToken, Delimiter, Token}; use rustc_ast::{ self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, @@ -23,7 +23,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::Span; +use rustc_span::{ErrorGuaranteed, Span}; use thin_vec::{thin_vec, ThinVec}; #[derive(PartialEq, Copy, Clone)] @@ -336,6 +336,95 @@ impl<'a> Parser<'a> { } } + /// Ensures that the last parsed pattern (or pattern range bound) is not followed by a method call or an operator. + /// + /// `is_end_bound` indicates whether the last parsed thing was the end bound of a range pattern (see [`parse_pat_range_end`](Self::parse_pat_range_end)) + /// in order to say "expected a pattern range bound" instead of "expected a pattern"; + /// ```text + /// 0..=1 + 2 + /// ^^^^^ + /// ``` + /// Only the end bound is spanned, and this function have no idea if there were a `..=` before `pat_span`, hence the parameter. + #[must_use = "the pattern must be discarded as `PatKind::Err` if this function returns Some"] + fn maybe_recover_trailing_expr( + &mut self, + pat_span: Span, + is_end_bound: bool, + ) -> Option { + if self.prev_token.is_keyword(kw::Underscore) || !self.may_recover() { + // Don't recover anything after an `_` or if recovery is disabled. + return None; + } + + // Check for `.hello()`, but allow `.Hello()` to be recovered as `, Hello()` in `parse_seq_to_before_tokens()`. + let has_trailing_method = self.check_noexpect(&token::Dot) + && self.look_ahead(1, |tok| { + tok.ident() + .and_then(|(ident, _)| ident.name.as_str().chars().next()) + .is_some_and(char::is_lowercase) + }) + && self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Parenthesis)); + + // Check for operators. + // `|` is excluded as it is used in pattern alternatives and lambdas, + // `?` is included for error propagation, + // `[` is included for indexing operations, + // `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`) + let has_trailing_operator = matches!(self.token.kind, token::BinOp(op) if op != BinOpToken::Or) + || self.token.kind == token::Question + || (self.token.kind == token::OpenDelim(Delimiter::Bracket) + && self.look_ahead(1, |tok| tok.kind != token::CloseDelim(Delimiter::Bracket))); + + if !has_trailing_method && !has_trailing_operator { + // Nothing to recover here. + return None; + } + + // Let's try to parse an expression to emit a better diagnostic. + let mut snapshot = self.create_snapshot_for_diagnostic(); + snapshot.restrictions.insert(Restrictions::IS_PAT); + + // Parse `?`, `.f`, `(arg0, arg1, ...)` or `[expr]` until they've all been eaten. + if let Ok(expr) = snapshot + .parse_expr_dot_or_call_with( + self.mk_expr_err(pat_span), // equivalent to transforming the parsed pattern into an `Expr` + pat_span, + AttrVec::new(), + ) + .map_err(|err| err.cancel()) + { + let non_assoc_span = expr.span; + + // Parse an associative expression such as `+ expr`, `% expr`, ... + // Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. + if let Ok(expr) = + snapshot.parse_expr_assoc_with(0, expr.into()).map_err(|err| err.cancel()) + { + // We got a valid expression. + self.restore_snapshot(snapshot); + self.restrictions.remove(Restrictions::IS_PAT); + + let is_bound = is_end_bound + // is_start_bound: either `..` or `)..` + || self.token.is_range_separator() + || self.token.kind == token::CloseDelim(Delimiter::Parenthesis) + && self.look_ahead(1, Token::is_range_separator); + + // Check that `parse_expr_assoc_with` didn't eat a rhs. + let is_method_call = has_trailing_method && non_assoc_span == expr.span; + + return Some(self.dcx().emit_err(UnexpectedExpressionInPattern { + span: expr.span, + is_bound, + is_method_call, + })); + } + } + + // We got a trailing method/operator, but we couldn't parse an expression. + None + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( @@ -441,7 +530,10 @@ impl<'a> Parser<'a> { } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { self.parse_pat_tuple_struct(qself, path)? } else { - PatKind::Path(qself, path) + match self.maybe_recover_trailing_expr(span, false) { + Some(guar) => PatKind::Err(guar), + None => PatKind::Path(qself, path), + } } } else if matches!(self.token.kind, token::Lifetime(_)) // In pattern position, we're totally fine with using "next token isn't colon" @@ -470,10 +562,17 @@ impl<'a> Parser<'a> { } else { // Try to parse everything else as literal with optional minus match self.parse_literal_maybe_minus() { - Ok(begin) => match self.parse_range_end() { - Some(form) => self.parse_pat_range_begin_with(begin, form)?, - None => PatKind::Lit(begin), - }, + Ok(begin) => { + let begin = match self.maybe_recover_trailing_expr(begin.span, false) { + Some(_) => self.mk_expr_err(begin.span), + None => begin, + }; + + match self.parse_range_end() { + Some(form) => self.parse_pat_range_begin_with(begin, form)?, + None => PatKind::Lit(begin), + } + } Err(err) => return self.fatal_unexpected_non_pat(err, expected), } }; @@ -615,6 +714,21 @@ impl<'a> Parser<'a> { self.parse_pat_range_begin_with(begin.clone(), form)? } + // recover ranges with parentheses around the `(start)..` + PatKind::Err(_) + if self.may_recover() + && let Some(form) = self.parse_range_end() => + { + self.dcx().emit_err(UnexpectedParenInRangePat { + span: vec![open_paren, close_paren], + sugg: UnexpectedParenInRangePatSugg { + start_span: open_paren, + end_span: close_paren, + }, + }); + + self.parse_pat_range_begin_with(self.mk_expr(pat.span, ExprKind::Err), form)? + } // (pat) with optional parentheses _ => PatKind::Paren(pat), @@ -853,6 +967,8 @@ impl<'a> Parser<'a> { self.parse_literal_maybe_minus() }?; + let recovered = self.maybe_recover_trailing_expr(bound.span, true); + // recover trailing `)` if let Some(open_paren) = open_paren { self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; @@ -866,7 +982,10 @@ impl<'a> Parser<'a> { }); } - Ok(bound) + Ok(match recovered { + Some(_) => self.mk_expr_err(bound.span), + None => bound, + }) } /// Is this the start of a pattern beginning with a path? @@ -929,7 +1048,17 @@ impl<'a> Parser<'a> { .create_err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span })); } - Ok(PatKind::Ident(binding_annotation, ident, sub)) + // Check for method calls after the `ident`, + // but not `ident @ subpat` as `subpat` was already checked and `ident` continues with `@`. + + let pat = if sub.is_none() + && let Some(guar) = self.maybe_recover_trailing_expr(ident.span, false) + { + PatKind::Err(guar) + } else { + PatKind::Ident(binding_annotation, ident, sub) + }; + Ok(pat) } /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`). diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs index 55353999b6788..0c050c550c4ce 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs @@ -17,12 +17,18 @@ fn main() { } match x as i32 { 0..5+1 => errors_only.push(x), - //~^ error: expected one of `=>`, `if`, or `|`, found `+` + //~^ error: expected a pattern range bound, found an expression + //~| error: exclusive range pattern syntax is experimental 1 | -3..0 => first_or.push(x), + //~^ error: exclusive range pattern syntax is experimental y @ (0..5 | 6) => or_two.push(y), + //~^ error: exclusive range pattern syntax is experimental y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + //~^ error: exclusive range pattern syntax is experimental + //~| error: inline-const in pattern position is experimental y @ -5.. => range_from.push(y), y @ ..-7 => assert_eq!(y, -8), + //~^ error: exclusive range pattern syntax is experimental y => bottom.push(y), } } diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr index cf3bde9705b6b..cc481f7a79e13 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -1,8 +1,8 @@ -error: expected one of `=>`, `if`, or `|`, found `+` - --> $DIR/range_pat_interactions1.rs:19:17 +error: expected a pattern range bound, found an expression + --> $DIR/range_pat_interactions1.rs:19:16 | LL | 0..5+1 => errors_only.push(x), - | ^ expected one of `=>`, `if`, or `|` + | ^^^ arbitrary expressions are not allowed in patterns error[E0408]: variable `n` is not bound in all patterns --> $DIR/range_pat_interactions1.rs:10:25 @@ -12,6 +12,16 @@ LL | if let n @ 2..3|4 = x { | | | variable not in all patterns +error[E0658]: inline-const in pattern position is experimental + --> $DIR/range_pat_interactions1.rs:26:20 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^ + | + = note: see issue #76001 for more information + = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: exclusive range pattern syntax is experimental --> $DIR/range_pat_interactions1.rs:10:20 | @@ -34,7 +44,62 @@ LL | } else if let 2..3 | 4 = x { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: use an inclusive range pattern, like N..=M -error: aborting due to 4 previous errors +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:19:13 + | +LL | 0..5+1 => errors_only.push(x), + | ^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:22:17 + | +LL | 1 | -3..0 => first_or.push(x), + | ^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:24:18 + | +LL | y @ (0..5 | 6) => or_two.push(y), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:26:17 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:30:17 + | +LL | y @ ..-7 => assert_eq!(y, -8), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error: aborting due to 10 previous errors Some errors have detailed explanations: E0408, E0658. For more information about an error, try `rustc --explain E0408`. diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs index 0e96cfe785857..068104c4b1b8c 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs @@ -8,12 +8,18 @@ fn main() { for x in -9 + 1..=(9 - 2) { match x as i32 { 0..=(5+1) => errors_only.push(x), - //~^ error: expected `)`, found `+` + //~^ error: expected a pattern range bound, found an expression + //~| error: range pattern bounds cannot have parentheses 1 | -3..0 => first_or.push(x), + //~^ error: exclusive range pattern syntax is experimental y @ (0..5 | 6) => or_two.push(y), + //~^ error: exclusive range pattern syntax is experimental y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + //~^ error: inline-const in pattern position is experimental + //~| error: exclusive range pattern syntax is experimental y @ -5.. => range_from.push(y), y @ ..-7 => assert_eq!(y, -8), + //~^ error: exclusive range pattern syntax is experimental y => bottom.push(y), } } diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr index a54f29a3b3263..8f21a6149fb89 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -1,8 +1,75 @@ -error: expected `)`, found `+` - --> $DIR/range_pat_interactions2.rs:10:19 +error: expected a pattern range bound, found an expression + --> $DIR/range_pat_interactions2.rs:10:18 | LL | 0..=(5+1) => errors_only.push(x), - | ^ expected `)` + | ^^^ arbitrary expressions are not allowed in patterns -error: aborting due to 1 previous error +error: range pattern bounds cannot have parentheses + --> $DIR/range_pat_interactions2.rs:10:17 + | +LL | 0..=(5+1) => errors_only.push(x), + | ^ ^ + | +help: remove these parentheses + | +LL - 0..=(5+1) => errors_only.push(x), +LL + 0..=5+1 => errors_only.push(x), + | + +error[E0658]: inline-const in pattern position is experimental + --> $DIR/range_pat_interactions2.rs:17:20 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^ + | + = note: see issue #76001 for more information + = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions2.rs:13:17 + | +LL | 1 | -3..0 => first_or.push(x), + | ^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions2.rs:15:18 + | +LL | y @ (0..5 | 6) => or_two.push(y), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions2.rs:17:17 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions2.rs:21:17 + | +LL | y @ ..-7 => assert_eq!(y, -8), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error: aborting due to 7 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/parser/issues/issue-24197.rs b/tests/ui/parser/issues/issue-24197.rs index aaf5137461fa6..9bba16e5596ff 100644 --- a/tests/ui/parser/issues/issue-24197.rs +++ b/tests/ui/parser/issues/issue-24197.rs @@ -1,3 +1,3 @@ fn main() { - let buf[0] = 0; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[` + let buf[0] = 0; //~ error: expected a pattern, found an expression } diff --git a/tests/ui/parser/issues/issue-24197.stderr b/tests/ui/parser/issues/issue-24197.stderr index 3ef707f3953cf..7ebbf4ac370d7 100644 --- a/tests/ui/parser/issues/issue-24197.stderr +++ b/tests/ui/parser/issues/issue-24197.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` - --> $DIR/issue-24197.rs:2:12 +error: expected a pattern, found an expression + --> $DIR/issue-24197.rs:2:9 | LL | let buf[0] = 0; - | ^ expected one of `:`, `;`, `=`, `@`, or `|` + | ^^^^^^ arbitrary expressions are not allowed in patterns error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-24375.rs b/tests/ui/parser/issues/issue-24375.rs index 1d128d33e4f49..a5e256b7f1554 100644 --- a/tests/ui/parser/issues/issue-24375.rs +++ b/tests/ui/parser/issues/issue-24375.rs @@ -3,7 +3,7 @@ static tmp : [&'static str; 2] = ["hello", "he"]; fn main() { let z = "hello"; match z { - tmp[0] => {} //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `[` + tmp[0] => {} //~ error: expected a pattern, found an expression _ => {} } } diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index bb1e19e9e6d8d..e6ef07d13fd8d 100644 --- a/tests/ui/parser/issues/issue-24375.stderr +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -1,8 +1,8 @@ -error: expected one of `=>`, `@`, `if`, or `|`, found `[` - --> $DIR/issue-24375.rs:6:12 +error: expected a pattern, found an expression + --> $DIR/issue-24375.rs:6:9 | LL | tmp[0] => {} - | ^ expected one of `=>`, `@`, `if`, or `|` + | ^^^^^^ arbitrary expressions are not allowed in patterns error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-lt-bracket-5.rs b/tests/ui/parser/pat-lt-bracket-5.rs index aaece1f6bd9cb..6d784494d56a3 100644 --- a/tests/ui/parser/pat-lt-bracket-5.rs +++ b/tests/ui/parser/pat-lt-bracket-5.rs @@ -1,3 +1,5 @@ fn main() { - let v[0] = v[1]; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[` + let v[0] = v[1]; + //~^ error: expected a pattern, found an expression + //~| error: cannot find value `v` in this scope } diff --git a/tests/ui/parser/pat-lt-bracket-5.stderr b/tests/ui/parser/pat-lt-bracket-5.stderr index e556e6c0206fb..18cf2df028216 100644 --- a/tests/ui/parser/pat-lt-bracket-5.stderr +++ b/tests/ui/parser/pat-lt-bracket-5.stderr @@ -1,8 +1,15 @@ -error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` - --> $DIR/pat-lt-bracket-5.rs:2:10 +error: expected a pattern, found an expression + --> $DIR/pat-lt-bracket-5.rs:2:9 | LL | let v[0] = v[1]; - | ^ expected one of `:`, `;`, `=`, `@`, or `|` + | ^^^^ arbitrary expressions are not allowed in patterns -error: aborting due to 1 previous error +error[E0425]: cannot find value `v` in this scope + --> $DIR/pat-lt-bracket-5.rs:2:16 + | +LL | let v[0] = v[1]; + | ^ not found in this scope + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/pat-lt-bracket-6.rs b/tests/ui/parser/pat-lt-bracket-6.rs index 7becffa9fe2f7..496525ed5370c 100644 --- a/tests/ui/parser/pat-lt-bracket-6.rs +++ b/tests/ui/parser/pat-lt-bracket-6.rs @@ -3,7 +3,8 @@ fn main() { let x = Test(&0, []); let Test(&desc[..]) = x; - //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` + //~^ error: expected a pattern, found an expression + //~| error: this pattern has 1 field, but the corresponding tuple struct has 2 fields } const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/tests/ui/parser/pat-lt-bracket-6.stderr b/tests/ui/parser/pat-lt-bracket-6.stderr index 035d0dbfe06d6..10c638a63e44c 100644 --- a/tests/ui/parser/pat-lt-bracket-6.stderr +++ b/tests/ui/parser/pat-lt-bracket-6.stderr @@ -1,18 +1,30 @@ -error: expected one of `)`, `,`, `@`, or `|`, found `[` - --> $DIR/pat-lt-bracket-6.rs:5:19 +error: expected a pattern, found an expression + --> $DIR/pat-lt-bracket-6.rs:5:15 | LL | let Test(&desc[..]) = x; - | ^ - | | - | expected one of `)`, `,`, `@`, or `|` - | help: missing `,` + | ^^^^^^^^ arbitrary expressions are not allowed in patterns error[E0308]: mismatched types - --> $DIR/pat-lt-bracket-6.rs:9:30 + --> $DIR/pat-lt-bracket-6.rs:10:30 | LL | const RECOVERY_WITNESS: () = 0; | ^ expected `()`, found integer -error: aborting due to 2 previous errors +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields + --> $DIR/pat-lt-bracket-6.rs:5:14 + | +LL | struct Test(&'static u8, [u8; 0]); + | ----------- ------- tuple struct has 2 fields +... +LL | let Test(&desc[..]) = x; + | ^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | let Test(&desc[..], _) = x; + | +++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0023, E0308. +For more information about an error, try `rustc --explain E0023`. diff --git a/tests/ui/parser/pat-ranges-3.rs b/tests/ui/parser/pat-ranges-3.rs index 8976dcf0d90f9..419768a2a2022 100644 --- a/tests/ui/parser/pat-ranges-3.rs +++ b/tests/ui/parser/pat-ranges-3.rs @@ -1,5 +1,9 @@ // Parsing of range patterns fn main() { - let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, `=`, or `|`, found `+` + let 10 ..= 10 + 3 = 12; + //~^ error: expected a pattern range bound, found an expression + + let 10 - 3 ..= 10 = 8; + //~^ error: expected a pattern range bound, found an expression } diff --git a/tests/ui/parser/pat-ranges-3.stderr b/tests/ui/parser/pat-ranges-3.stderr index 611b35a650280..5e1f35d1b6f9a 100644 --- a/tests/ui/parser/pat-ranges-3.stderr +++ b/tests/ui/parser/pat-ranges-3.stderr @@ -1,8 +1,14 @@ -error: expected one of `:`, `;`, `=`, or `|`, found `+` - --> $DIR/pat-ranges-3.rs:4:19 +error: expected a pattern range bound, found an expression + --> $DIR/pat-ranges-3.rs:4:16 | LL | let 10 ..= 10 + 3 = 12; - | ^ expected one of `:`, `;`, `=`, or `|` + | ^^^^^^ arbitrary expressions are not allowed in patterns -error: aborting due to 1 previous error +error: expected a pattern range bound, found an expression + --> $DIR/pat-ranges-3.rs:7:9 + | +LL | let 10 - 3 ..= 10 = 8; + | ^^^^^^ arbitrary expressions are not allowed in patterns + +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/pat-ranges-4.rs b/tests/ui/parser/pat-ranges-4.rs deleted file mode 100644 index 61188976b028c..0000000000000 --- a/tests/ui/parser/pat-ranges-4.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Parsing of range patterns - -fn main() { - let 10 - 3 ..= 10 = 8; - //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` -} diff --git a/tests/ui/parser/pat-ranges-4.stderr b/tests/ui/parser/pat-ranges-4.stderr deleted file mode 100644 index c30160291d608..0000000000000 --- a/tests/ui/parser/pat-ranges-4.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` - --> $DIR/pat-ranges-4.rs:4:12 - | -LL | let 10 - 3 ..= 10 = 8; - | ^ expected one of 7 possible tokens - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/pat-recover-exprs.rs b/tests/ui/parser/pat-recover-exprs.rs new file mode 100644 index 0000000000000..ecd471467e380 --- /dev/null +++ b/tests/ui/parser/pat-recover-exprs.rs @@ -0,0 +1,28 @@ +fn main() { + match u8::MAX { + u8::MAX.abs() => (), + //~^ error: expected a pattern, found a method call + x.sqrt() @ .. => (), + //~^ error: expected a pattern, found a method call + //~| error: left-hand side of `@` must be a binding + z @ w @ v.u() => (), + //~^ error: expected a pattern, found a method call + y.ilog(3) => (), + //~^ error: expected a pattern, found a method call + n + 1 => (), + //~^ error: expected a pattern, found an expression + ("".f() + 14 * 8) => (), + //~^ error: expected a pattern, found an expression + 0 | ((1) | 2) | 3 => (), + f?() => (), + //~^ error: expected a pattern, found an expression + (_ + 1) => (), + //~^ error: expected one of `)`, `,`, or `|`, found `+` + } + + let 1 + 1 = 2; + //~^ error: expected a pattern, found an expression + + let b = matches!(x, (x * x | x.f()) | x[0]); + //~^ error: expected one of `)`, `,`, `@`, or `|`, found `*` +} diff --git a/tests/ui/parser/pat-recover-exprs.stderr b/tests/ui/parser/pat-recover-exprs.stderr new file mode 100644 index 0000000000000..787fd03b0c30d --- /dev/null +++ b/tests/ui/parser/pat-recover-exprs.stderr @@ -0,0 +1,76 @@ +error: expected a pattern, found a method call + --> $DIR/pat-recover-exprs.rs:3:9 + | +LL | u8::MAX.abs() => (), + | ^^^^^^^^^^^^^ method calls are not allowed in patterns + +error: expected a pattern, found a method call + --> $DIR/pat-recover-exprs.rs:5:9 + | +LL | x.sqrt() @ .. => (), + | ^^^^^^^^ method calls are not allowed in patterns + +error: left-hand side of `@` must be a binding + --> $DIR/pat-recover-exprs.rs:5:9 + | +LL | x.sqrt() @ .. => (), + | --------^^^-- + | | | + | | also a pattern + | interpreted as a pattern, not a binding + | + = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` + +error: expected a pattern, found a method call + --> $DIR/pat-recover-exprs.rs:8:17 + | +LL | z @ w @ v.u() => (), + | ^^^^^ method calls are not allowed in patterns + +error: expected a pattern, found a method call + --> $DIR/pat-recover-exprs.rs:10:9 + | +LL | y.ilog(3) => (), + | ^^^^^^^^^ method calls are not allowed in patterns + +error: expected a pattern, found an expression + --> $DIR/pat-recover-exprs.rs:12:9 + | +LL | n + 1 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + +error: expected a pattern, found an expression + --> $DIR/pat-recover-exprs.rs:14:10 + | +LL | ("".f() + 14 * 8) => (), + | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + +error: expected a pattern, found an expression + --> $DIR/pat-recover-exprs.rs:17:9 + | +LL | f?() => (), + | ^^^^ arbitrary expressions are not allowed in patterns + +error: expected one of `)`, `,`, or `|`, found `+` + --> $DIR/pat-recover-exprs.rs:19:12 + | +LL | (_ + 1) => (), + | ^ expected one of `)`, `,`, or `|` + +error: expected a pattern, found an expression + --> $DIR/pat-recover-exprs.rs:23:9 + | +LL | let 1 + 1 = 2; + | ^^^^^ arbitrary expressions are not allowed in patterns + +error: expected one of `)`, `,`, `@`, or `|`, found `*` + --> $DIR/pat-recover-exprs.rs:26:28 + | +LL | let b = matches!(x, (x * x | x.f()) | x[0]); + | ^ expected one of `)`, `,`, `@`, or `|` + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + | + = note: while parsing argument for this `pat` macro fragment + +error: aborting due to 11 previous errors + diff --git a/tests/ui/parser/pat-recover-methodcalls.rs b/tests/ui/parser/pat-recover-methodcalls.rs new file mode 100644 index 0000000000000..54104e9a53559 --- /dev/null +++ b/tests/ui/parser/pat-recover-methodcalls.rs @@ -0,0 +1,37 @@ +struct Foo(String); +struct Bar { baz: String } + +fn foo(foo: Foo) -> bool { + match foo { + Foo("hi".to_owned()) => true, + //~^ error: expected a pattern, found a method call + _ => false + } +} + +fn bar(bar: Bar) -> bool { + match bar { + Bar { baz: "hi".to_owned() } => true, + //~^ error: expected a pattern, found a method call + _ => false + } +} + +fn baz() { // issue #90121 + let foo = vec!["foo".to_string()]; + + match foo.as_slice() { + &["foo".to_string()] => {} + //~^ error: expected a pattern, found a method call + _ => {} + }; +} + +fn main() { + if let (-1.some(4)) = (0, Some(4)) {} + //~^ error: expected a pattern, found a method call + + if let (-1.Some(4)) = (0, Some(4)) {} + //~^ error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.` + //~| help: missing `,` +} diff --git a/tests/ui/parser/pat-recover-methodcalls.stderr b/tests/ui/parser/pat-recover-methodcalls.stderr new file mode 100644 index 0000000000000..1f9ae81dc0c55 --- /dev/null +++ b/tests/ui/parser/pat-recover-methodcalls.stderr @@ -0,0 +1,35 @@ +error: expected a pattern, found a method call + --> $DIR/pat-recover-methodcalls.rs:6:13 + | +LL | Foo("hi".to_owned()) => true, + | ^^^^^^^^^^^^^^^ method calls are not allowed in patterns + +error: expected a pattern, found a method call + --> $DIR/pat-recover-methodcalls.rs:14:20 + | +LL | Bar { baz: "hi".to_owned() } => true, + | ^^^^^^^^^^^^^^^ method calls are not allowed in patterns + +error: expected a pattern, found a method call + --> $DIR/pat-recover-methodcalls.rs:24:11 + | +LL | &["foo".to_string()] => {} + | ^^^^^^^^^^^^^^^^^ method calls are not allowed in patterns + +error: expected a pattern, found a method call + --> $DIR/pat-recover-methodcalls.rs:31:13 + | +LL | if let (-1.some(4)) = (0, Some(4)) {} + | ^^^^^^^^^^ method calls are not allowed in patterns + +error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.` + --> $DIR/pat-recover-methodcalls.rs:34:15 + | +LL | if let (-1.Some(4)) = (0, Some(4)) {} + | ^ + | | + | expected one of `)`, `,`, `...`, `..=`, `..`, or `|` + | help: missing `,` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/pat-recover-ranges.rs b/tests/ui/parser/pat-recover-ranges.rs index 65a6fc6fe21f3..7d77e950d905a 100644 --- a/tests/ui/parser/pat-recover-ranges.rs +++ b/tests/ui/parser/pat-recover-ranges.rs @@ -8,6 +8,22 @@ fn main() { (0)..=(-4) => (), //~^ error: range pattern bounds cannot have parentheses //~| error: range pattern bounds cannot have parentheses + ..=1 + 2 => (), + //~^ error: expected a pattern range bound, found an expression + (4).. => (), + //~^ error: range pattern bounds cannot have parentheses + (-4 + 0).. => (), + //~^ error: expected a pattern range bound, found an expression + //~| error: range pattern bounds cannot have parentheses + (1 + 4)...1 * 2 => (), + //~^ error: expected a pattern range bound, found an expression + //~| error: expected a pattern range bound, found an expression + //~| error: range pattern bounds cannot have parentheses + //~| warning: `...` range patterns are deprecated + //~| warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + 0.x()..="y".z() => (), + //~^ error: expected a pattern range bound, found a method call + //~| error: expected a pattern range bound, found a method call }; } diff --git a/tests/ui/parser/pat-recover-ranges.stderr b/tests/ui/parser/pat-recover-ranges.stderr index 0d722b5aa95c8..a7d62bd7f8ad2 100644 --- a/tests/ui/parser/pat-recover-ranges.stderr +++ b/tests/ui/parser/pat-recover-ranges.stderr @@ -46,5 +46,87 @@ LL - (0)..=(-4) => (), LL + (0)..=-4 => (), | -error: aborting due to 4 previous errors +error: expected a pattern range bound, found an expression + --> $DIR/pat-recover-ranges.rs:11:12 + | +LL | ..=1 + 2 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + +error: range pattern bounds cannot have parentheses + --> $DIR/pat-recover-ranges.rs:13:9 + | +LL | (4).. => (), + | ^ ^ + | +help: remove these parentheses + | +LL - (4).. => (), +LL + 4.. => (), + | + +error: expected a pattern range bound, found an expression + --> $DIR/pat-recover-ranges.rs:15:10 + | +LL | (-4 + 0).. => (), + | ^^^^^^ arbitrary expressions are not allowed in patterns + +error: range pattern bounds cannot have parentheses + --> $DIR/pat-recover-ranges.rs:15:9 + | +LL | (-4 + 0).. => (), + | ^ ^ + | +help: remove these parentheses + | +LL - (-4 + 0).. => (), +LL + -4 + 0.. => (), + | + +error: expected a pattern range bound, found an expression + --> $DIR/pat-recover-ranges.rs:18:10 + | +LL | (1 + 4)...1 * 2 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + +error: range pattern bounds cannot have parentheses + --> $DIR/pat-recover-ranges.rs:18:9 + | +LL | (1 + 4)...1 * 2 => (), + | ^ ^ + | +help: remove these parentheses + | +LL - (1 + 4)...1 * 2 => (), +LL + 1 + 4...1 * 2 => (), + | + +error: expected a pattern range bound, found an expression + --> $DIR/pat-recover-ranges.rs:18:19 + | +LL | (1 + 4)...1 * 2 => (), + | ^^^^^ arbitrary expressions are not allowed in patterns + +error: expected a pattern range bound, found a method call + --> $DIR/pat-recover-ranges.rs:24:9 + | +LL | 0.x()..="y".z() => (), + | ^^^^^ method calls are not allowed in patterns + +error: expected a pattern range bound, found a method call + --> $DIR/pat-recover-ranges.rs:24:17 + | +LL | 0.x()..="y".z() => (), + | ^^^^^^^ method calls are not allowed in patterns + +warning: `...` range patterns are deprecated + --> $DIR/pat-recover-ranges.rs:18:16 + | +LL | (1 + 4)...1 * 2 => (), + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default + +error: aborting due to 13 previous errors; 1 warning emitted diff --git a/tests/ui/parser/pat-recover-wildcards.rs b/tests/ui/parser/pat-recover-wildcards.rs new file mode 100644 index 0000000000000..f506e2223d608 --- /dev/null +++ b/tests/ui/parser/pat-recover-wildcards.rs @@ -0,0 +1,61 @@ +// check that we can't do funny things with wildcards. + +fn a() { + match 1 { + _ + 1 => () //~ error: expected one of `=>`, `if`, or `|`, found `+` + } +} + +fn b() { + match 2 { + (_ % 4) => () //~ error: expected one of `)`, `,`, or `|`, found `%` + } +} + +fn c() { + match 3 { + _.x() => () //~ error: expected one of `=>`, `if`, or `|`, found `.` + } +} + +fn d() { + match 4 { + _..=4 => () //~ error: expected one of `=>`, `if`, or `|`, found `..=` + } +} + +fn e() { + match 5 { + .._ => () //~ error: expected one of `=>`, `if`, or `|`, found reserved identifier `_` + } +} + +fn f() { + match 6 { + 0..._ => () + //~^ error: inclusive range with no end + //~| error: expected one of `=>`, `if`, or `|`, found reserved identifier `_` + } +} + +fn g() { + match 7 { + (_ * 0)..5 => () //~ error: expected one of `)`, `,`, or `|`, found `*` + } +} + +fn h() { + match 8 { + ..(_) => () //~ error: expected one of `=>`, `if`, or `|`, found `(` + } +} + +fn i() { + match 9 { + 4..=(2 + _) => () + //~^ error: expected a pattern range bound, found an expression + //~| error: range pattern bounds cannot have parentheses + } +} + +fn main() {} diff --git a/tests/ui/parser/pat-recover-wildcards.stderr b/tests/ui/parser/pat-recover-wildcards.stderr new file mode 100644 index 0000000000000..2b0c9bbc5be86 --- /dev/null +++ b/tests/ui/parser/pat-recover-wildcards.stderr @@ -0,0 +1,77 @@ +error: expected one of `=>`, `if`, or `|`, found `+` + --> $DIR/pat-recover-wildcards.rs:5:11 + | +LL | _ + 1 => () + | ^ expected one of `=>`, `if`, or `|` + +error: expected one of `)`, `,`, or `|`, found `%` + --> $DIR/pat-recover-wildcards.rs:11:12 + | +LL | (_ % 4) => () + | ^ expected one of `)`, `,`, or `|` + +error: expected one of `=>`, `if`, or `|`, found `.` + --> $DIR/pat-recover-wildcards.rs:17:10 + | +LL | _.x() => () + | ^ expected one of `=>`, `if`, or `|` + +error: expected one of `=>`, `if`, or `|`, found `..=` + --> $DIR/pat-recover-wildcards.rs:23:10 + | +LL | _..=4 => () + | ^^^ expected one of `=>`, `if`, or `|` + +error: expected one of `=>`, `if`, or `|`, found reserved identifier `_` + --> $DIR/pat-recover-wildcards.rs:29:11 + | +LL | .._ => () + | ^ expected one of `=>`, `if`, or `|` + +error[E0586]: inclusive range with no end + --> $DIR/pat-recover-wildcards.rs:35:10 + | +LL | 0..._ => () + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: expected one of `=>`, `if`, or `|`, found reserved identifier `_` + --> $DIR/pat-recover-wildcards.rs:35:13 + | +LL | 0..._ => () + | ^ expected one of `=>`, `if`, or `|` + +error: expected one of `)`, `,`, or `|`, found `*` + --> $DIR/pat-recover-wildcards.rs:43:12 + | +LL | (_ * 0)..5 => () + | ^ expected one of `)`, `,`, or `|` + +error: expected one of `=>`, `if`, or `|`, found `(` + --> $DIR/pat-recover-wildcards.rs:49:11 + | +LL | ..(_) => () + | ^ expected one of `=>`, `if`, or `|` + +error: expected a pattern range bound, found an expression + --> $DIR/pat-recover-wildcards.rs:55:14 + | +LL | 4..=(2 + _) => () + | ^^^^^ arbitrary expressions are not allowed in patterns + +error: range pattern bounds cannot have parentheses + --> $DIR/pat-recover-wildcards.rs:55:13 + | +LL | 4..=(2 + _) => () + | ^ ^ + | +help: remove these parentheses + | +LL - 4..=(2 + _) => () +LL + 4..=2 + _ => () + | + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0586`. From c36798357d353a8df1bf430ea3261741cfc51121 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 28 Jan 2024 11:13:02 +0800 Subject: [PATCH 319/676] Suggest name value cfg when only value is used for check-cfg --- .../rustc_lint/src/context/diagnostics.rs | 50 +++++++++++++++---- .../cfg-value-for-cfg-name-multiple.rs | 12 +++++ .../cfg-value-for-cfg-name-multiple.stderr | 21 ++++++++ tests/ui/check-cfg/cfg-value-for-cfg-name.rs | 18 +++++++ .../check-cfg/cfg-value-for-cfg-name.stderr | 22 ++++++++ 5 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs create mode 100644 tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr create mode 100644 tests/ui/check-cfg/cfg-value-for-cfg-name.rs create mode 100644 tests/ui/check-cfg/cfg-value-for-cfg-name.stderr diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 312874db3f54e..31205f2b2fd97 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -187,6 +187,23 @@ pub(super) fn builtin( BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => { let possibilities: Vec = sess.parse_sess.check_config.expecteds.keys().copied().collect(); + + let mut names_possibilities: Vec<_> = if value.is_none() { + // We later sort and display all the possibilities, so the order here does not matter. + #[allow(rustc::potential_query_instability)] + sess.parse_sess + .check_config + .expecteds + .iter() + .filter_map(|(k, v)| match v { + ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k), + _ => None, + }) + .collect() + } else { + Vec::new() + }; + let is_from_cargo = std::env::var_os("CARGO").is_some(); let mut is_feature_cfg = name == sym::feature; @@ -261,17 +278,30 @@ pub(super) fn builtin( } is_feature_cfg |= best_match == sym::feature; - } else if !possibilities.is_empty() { - let mut possibilities = - possibilities.iter().map(Symbol::as_str).collect::>(); - possibilities.sort(); - let possibilities = possibilities.join("`, `"); + } else { + if !names_possibilities.is_empty() { + names_possibilities.sort(); + for cfg_name in names_possibilities.iter() { + db.span_suggestion( + name_span, + "found config with similar value", + format!("{cfg_name} = \"{name}\""), + Applicability::MaybeIncorrect, + ); + } + } + if !possibilities.is_empty() { + let mut possibilities = + possibilities.iter().map(Symbol::as_str).collect::>(); + possibilities.sort(); + let possibilities = possibilities.join("`, `"); - // The list of expected names can be long (even by default) and - // so the diagnostic produced can take a lot of space. To avoid - // cloging the user output we only want to print that diagnostic - // once. - db.help_once(format!("expected names are: `{possibilities}`")); + // The list of expected names can be long (even by default) and + // so the diagnostic produced can take a lot of space. To avoid + // cloging the user output we only want to print that diagnostic + // once. + db.help_once(format!("expected names are: `{possibilities}`")); + } } let inst = if let Some((value, _value_span)) = value { diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs new file mode 100644 index 0000000000000..edde6244ed1a9 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs @@ -0,0 +1,12 @@ +// #120427 +// This test checks that when a single cfg has a value for user's specified name +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(foo,values("my_value")) --check-cfg=cfg(bar,values("my_value")) + +#[cfg(my_value)] +//~^ WARNING unexpected `cfg` condition name: `my_value` +fn x() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr new file mode 100644 index 0000000000000..b88ee71a156a2 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr @@ -0,0 +1,21 @@ +warning: unexpected `cfg` condition name: `my_value` + --> $DIR/cfg-value-for-cfg-name-multiple.rs:8:7 + | +LL | #[cfg(my_value)] + | ^^^^^^^^ + | + = help: expected names are: `bar`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(my_value)` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default +help: found config with similar value + | +LL | #[cfg(foo = "my_value")] + | ~~~~~~~~~~~~~~~~ +help: found config with similar value + | +LL | #[cfg(bar = "my_value")] + | ~~~~~~~~~~~~~~~~ + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs new file mode 100644 index 0000000000000..7a0c345b7ca76 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs @@ -0,0 +1,18 @@ +// #120427 +// This test checks that when a single cfg has a value for user's specified name +// suggest to use `#[cfg(target_os = "linux")]` instead of `#[cfg(linux)]` +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg() + +#[cfg(linux)] +//~^ WARNING unexpected `cfg` condition name: `linux` +fn x() {} + +// will not suggest if the cfg has a value +#[cfg(linux = "os-name")] +//~^ WARNING unexpected `cfg` condition name: `linux` +fn y() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr new file mode 100644 index 0000000000000..c044755142419 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr @@ -0,0 +1,22 @@ +warning: unexpected `cfg` condition name: `linux` + --> $DIR/cfg-value-for-cfg-name.rs:9:7 + | +LL | #[cfg(linux)] + | ^^^^^ help: found config with similar value: `target_os = "linux"` + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(linux)` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition name: `linux` + --> $DIR/cfg-value-for-cfg-name.rs:14:7 + | +LL | #[cfg(linux = "os-name")] + | ^^^^^^^^^^^^^^^^^ + | + = help: to expect this configuration use `--check-cfg=cfg(linux, values("os-name"))` + = note: see for more information about checking conditional configuration + +warning: 2 warnings emitted + From 8302e25529b88f4c2f561ca519bcb4faf34bc25f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Jan 2024 16:45:52 +0100 Subject: [PATCH 320/676] tweak comments --- src/tools/miri/src/helpers.rs | 2 +- src/tools/miri/src/shims/unix/fs.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 3651db982b3a1..eb9d8e8e68e77 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -225,7 +225,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { bug!("No field named {} in type {}", name, base.layout().ty); } - /// Search if Project (which must be a struct or union type) contains the `name` field. + /// Search if `base` (which must be a struct or union type) contains the `name` field. fn projectable_has_field>( &self, base: &P, diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index b2170c8c87fd3..5b93db19d5510 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1466,8 +1466,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ], &entry_place, )?; - // freebsd 12 and onwards had added the d_off field } else if this.projectable_has_field(&entry_place, "d_off") { + // freebsd 12 and onwards had added the d_off field this.write_int_fields_named( &[ ("d_fileno", ino.into()), From 09e0d4f89a2c591b0d131fe0ddc8dd7bd7f20092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 28 Jan 2024 17:01:47 +0100 Subject: [PATCH 321/676] Print image input file and Docker version --- src/ci/docker/run.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 442b870e709f6..0db61204f77f2 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -84,8 +84,13 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then context="$script_dir" fi echo "::group::Building docker image for $image" + echo "Image input" + cat $hash_key echo "Image input checksum ${cksum}" + # Print docker version + docker --version + # On non-CI or PR jobs, we don't have permissions to write to the registry cache, so we should # not use `docker login` nor caching. if [[ "$CI" == "" ]] || [[ "$PR_CI_JOB" == "1" ]]; 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 322/676] 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 323/676] 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 324/676] 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 6837b812e69a0c024021e3a828bcdc5c7d8f1b4d Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sun, 28 Jan 2024 12:19:41 +0100 Subject: [PATCH 325/676] Fix some `Arc` allocator leaks This doesn't matter for the stable `Global` allocator as it is a ZST singleton, but other allocators may rely on all instances being dropped. --- library/alloc/src/sync.rs | 44 ++++++++++------------ library/alloc/src/sync/tests.rs | 65 ++++++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 48c8d9d113b06..29b00c97b47b7 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -279,6 +279,12 @@ impl Arc { } impl Arc { + #[inline] + fn internal_into_inner_with_allocator(self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(self); + (this.ptr, unsafe { ptr::read(&this.alloc) }) + } + #[inline] unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { Self { ptr, phantom: PhantomData, alloc } @@ -1271,12 +1277,9 @@ impl Arc, A> { #[unstable(feature = "new_uninit", issue = "63291")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] - pub unsafe fn assume_init(self) -> Arc - where - A: Clone, - { - let md_self = mem::ManuallyDrop::new(self); - unsafe { Arc::from_inner_in(md_self.ptr.cast(), md_self.alloc.clone()) } + pub unsafe fn assume_init(self) -> Arc { + let (ptr, alloc) = self.internal_into_inner_with_allocator(); + unsafe { Arc::from_inner_in(ptr.cast(), alloc) } } } @@ -1316,12 +1319,9 @@ impl Arc<[mem::MaybeUninit], A> { #[unstable(feature = "new_uninit", issue = "63291")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] - pub unsafe fn assume_init(self) -> Arc<[T], A> - where - A: Clone, - { - let md_self = mem::ManuallyDrop::new(self); - unsafe { Arc::from_ptr_in(md_self.ptr.as_ptr() as _, md_self.alloc.clone()) } + pub unsafe fn assume_init(self) -> Arc<[T], A> { + let (ptr, alloc) = self.internal_into_inner_with_allocator(); + unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -2409,7 +2409,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc { } } -impl Arc { +impl Arc { /// Attempt to downcast the `Arc` to a concrete type. /// /// # Examples @@ -2436,10 +2436,8 @@ impl Arc { { if (*self).is::() { unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - mem::forget(self); - Ok(Arc::from_inner_in(ptr, alloc)) + let (ptr, alloc) = self.internal_into_inner_with_allocator(); + Ok(Arc::from_inner_in(ptr.cast(), alloc)) } } else { Err(self) @@ -2479,10 +2477,8 @@ impl Arc { T: Any + Send + Sync, { unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - mem::forget(self); - Arc::from_inner_in(ptr, alloc) + let (ptr, alloc) = self.internal_into_inner_with_allocator(); + Arc::from_inner_in(ptr.cast(), alloc) } } } @@ -3438,13 +3434,13 @@ impl From> for Arc<[u8]> { } #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] -impl TryFrom> for Arc<[T; N], A> { +impl TryFrom> for Arc<[T; N], A> { type Error = Arc<[T], A>; fn try_from(boxed_slice: Arc<[T], A>) -> Result { if boxed_slice.len() == N { - let alloc = boxed_slice.alloc.clone(); - Ok(unsafe { Arc::from_raw_in(Arc::into_raw(boxed_slice) as *mut [T; N], alloc) }) + let (ptr, alloc) = boxed_slice.internal_into_inner_with_allocator(); + Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) }) } else { Err(boxed_slice) } diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index d37e45569cf0f..49eae718c1690 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -1,13 +1,15 @@ use super::*; use std::clone::Clone; +use std::mem::MaybeUninit; use std::option::Option::None; +use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::SeqCst; use std::sync::mpsc::channel; use std::sync::Mutex; use std::thread; -struct Canary(*mut atomic::AtomicUsize); +struct Canary(*mut AtomicUsize); impl Drop for Canary { fn drop(&mut self) { @@ -21,6 +23,37 @@ impl Drop for Canary { } } +struct AllocCanary<'a>(&'a AtomicUsize); + +impl<'a> AllocCanary<'a> { + fn new(counter: &'a AtomicUsize) -> Self { + counter.fetch_add(1, SeqCst); + Self(counter) + } +} + +unsafe impl Allocator for AllocCanary<'_> { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + std::alloc::Global.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + unsafe { std::alloc::Global.deallocate(ptr, layout) } + } +} + +impl Clone for AllocCanary<'_> { + fn clone(&self) -> Self { + Self::new(self.0) + } +} + +impl Drop for AllocCanary<'_> { + fn drop(&mut self) { + self.0.fetch_sub(1, SeqCst); + } +} + #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn manually_share_arc() { @@ -295,16 +328,16 @@ fn weak_self_cyclic() { #[test] fn drop_arc() { - let mut canary = atomic::AtomicUsize::new(0); - let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + let mut canary = AtomicUsize::new(0); + let x = Arc::new(Canary(&mut canary as *mut AtomicUsize)); drop(x); assert!(canary.load(Acquire) == 1); } #[test] fn drop_arc_weak() { - let mut canary = atomic::AtomicUsize::new(0); - let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + let mut canary = AtomicUsize::new(0); + let arc = Arc::new(Canary(&mut canary as *mut AtomicUsize)); let arc_weak = Arc::downgrade(&arc); assert!(canary.load(Acquire) == 0); drop(arc); @@ -660,3 +693,25 @@ fn arc_drop_dereferenceable_race() { thread.join().unwrap(); } } + +#[test] +fn arc_doesnt_leak_allocator() { + let counter = AtomicUsize::new(0); + + { + let arc: Arc = Arc::new_in(5usize, AllocCanary::new(&counter)); + drop(arc.downcast::().unwrap()); + + let arc: Arc = Arc::new_in(5usize, AllocCanary::new(&counter)); + drop(unsafe { arc.downcast_unchecked::() }); + + let arc = Arc::new_in(MaybeUninit::::new(5usize), AllocCanary::new(&counter)); + drop(unsafe { arc.assume_init() }); + + let arc: Arc<[MaybeUninit], _> = + Arc::new_zeroed_slice_in(5, AllocCanary::new(&counter)); + drop(unsafe { arc.assume_init() }); + } + + assert_eq!(counter.load(SeqCst), 0); +} From b85b2a783b813def53b2a7f0c9b53fed119e2338 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 28 Jan 2024 11:24:27 -0800 Subject: [PATCH 326/676] std: Update documentation of seek_write on Windows Currently the documentation of `FileExt::seek_write` on Windows indicates that writes beyond the end of the file leave intermediate bytes uninitialized. This commentary dates back to the original inclusion of these functions in #35704 (wow blast from the past!). At the time the functionality here was implemented using `WriteFile`, but nowadays the `NtWriteFile` method is used instead. The documentation for `NtWriteFile` explicitly states: > If Length and ByteOffset specify a write operation past the current > end-of-file mark, NtWriteFile automatically extends the file and updates > the end-of-file mark; any bytes that are not explicitly written between > such old and new end-of-file marks are defined to be zero. This commentary has had a downstream impact in the `system-interface` crate where it tries to handle this by explicitly writing zeros, but I don't believe that's necessary any more. I'm sending a PR upstream here to avoid future confusion and codify that zeros are written in the intermediate bytes matching what Windows currently provides. --- library/std/src/os/windows/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 1b013d1c154c9..e9d7a13e9d5b2 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -59,7 +59,7 @@ pub trait FileExt { /// function, it is set to the end of the write. /// /// When writing beyond the end of the file, the file is appropriately - /// extended and the intermediate bytes are left uninitialized. + /// extended and the intermediate bytes are set to zero. /// /// Note that similar to `File::write`, it is not an error to return a /// short write. When returning from such a short write, the file pointer From 67558055e39ee44be32ad4eb77052b1cd2ee3158 Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Sun, 28 Jan 2024 19:30:00 +0000 Subject: [PATCH 327/676] normalize_newlines(): fix incorrect comment --- compiler/rustc_span/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 65702f76fdac7..ea6766ea583be 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2105,7 +2105,7 @@ fn remove_bom(src: &mut String, normalized_pos: &mut Vec) { /// Replaces `\r\n` with `\n` in-place in `src`. /// -/// Returns error if there's a lone `\r` in the string. +/// Leaves any occurrences of lone `\r` unchanged. fn normalize_newlines(src: &mut String, normalized_pos: &mut Vec) { if !src.as_bytes().contains(&b'\r') { return; From f38489e957a1f169be4071947a4426885793f03b Mon Sep 17 00:00:00 2001 From: Jarl Evanson Date: Sun, 28 Jan 2024 13:47:52 -0600 Subject: [PATCH 328/676] Enable `remove_storage_markers` MIR-opt test --- tests/mir-opt/remove_storage_markers.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/remove_storage_markers.rs b/tests/mir-opt/remove_storage_markers.rs index 6666ff3b7263b..74e399b6c0eed 100644 --- a/tests/mir-opt/remove_storage_markers.rs +++ b/tests/mir-opt/remove_storage_markers.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: RemoveStorageMarkers @@ -8,6 +7,10 @@ // EMIT_MIR remove_storage_markers.main.RemoveStorageMarkers.diff fn main() { + // CHECK-LABLE: fn main( + + // CHECK-NOT: StorageDead + // CHECK-NOT: StorageLive let mut sum = 0; for i in 0..10 { sum += i; From d1edc9d0dbd4ce9f1d71eba2ae4116efea8a6f2f Mon Sep 17 00:00:00 2001 From: Jarl Evanson Date: Sun, 28 Jan 2024 13:50:20 -0600 Subject: [PATCH 329/676] Enable `simplify` MIR-opt test --- tests/mir-opt/simplify_if.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/simplify_if.rs b/tests/mir-opt/simplify_if.rs index 19b5806f72094..f600c05958198 100644 --- a/tests/mir-opt/simplify_if.rs +++ b/tests/mir-opt/simplify_if.rs @@ -1,10 +1,13 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #[inline(never)] fn noop() {} // EMIT_MIR simplify_if.main.SimplifyConstCondition-after-const-prop.diff fn main() { + // CHECK-LABEL: fn main( + + // CHECK: bb0: { + // CHECK-NEXT: return; if false { noop(); } From d91d164b00d63ade539f206fb9bf8cac5c8c73e3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 14 Jan 2024 10:57:35 +1100 Subject: [PATCH 330/676] Sort attributes in `compiler/rustc_errors/src/lib.rs`. As is already done in `rustc_span` and `rustc_data_structures`. --- compiler/rustc_errors/src/lib.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ee831c4f560c0..a64ad2beb6c54 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -2,23 +2,25 @@ //! //! This module contains the code for creating and emitting diagnostics. +// tidy-alphabetical-start +#![allow(incomplete_features)] +#![allow(internal_features)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] -#![feature(rustdoc_internals)] #![feature(array_windows)] #![feature(associated_type_defaults)] #![feature(box_into_inner)] #![feature(box_patterns)] +#![feature(error_reporter)] #![feature(extract_if)] #![feature(let_chains)] #![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] -#![feature(yeet_expr)] +#![feature(rustdoc_internals)] #![feature(try_blocks)] -#![feature(error_reporter)] -#![allow(incomplete_features)] -#![allow(internal_features)] +#![feature(yeet_expr)] +// tidy-alphabetical-end #[macro_use] extern crate rustc_macros; From 0321de27784f427057897f6b5693c97390e98371 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 14 Jan 2024 22:18:48 +1100 Subject: [PATCH 331/676] Remove bogus `{code}` attributes on `TraitImplMismatch`. This makes no sense, and has no effect. I suspect it's been confused with a `code = "{code}"` attribute on a subdiagnostic suggestion, where it is valid (but the "code" there is suggested source code, rather than an error code.) --- compiler/rustc_resolve/src/errors.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 821b1e946f31c..5d9269d8f542c 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -456,7 +456,7 @@ pub(crate) struct UnreachableLabelSubLabelUnreachable { } #[derive(Diagnostic)] -#[diag(resolve_trait_impl_mismatch, code = "{code}")] +#[diag(resolve_trait_impl_mismatch)] pub(crate) struct TraitImplMismatch { #[primary_span] #[label] @@ -466,7 +466,6 @@ pub(crate) struct TraitImplMismatch { #[label(resolve_label_trait_item)] pub(crate) trait_item_span: Span, pub(crate) trait_path: String, - pub(crate) code: String, } #[derive(Diagnostic)] From 5d9dfbd08f38c2a9bc71d39de8f5c7776afe0f9e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 14 Jan 2024 10:57:07 +1100 Subject: [PATCH 332/676] Stop using `String` for error codes. Error codes are integers, but `String` is used everywhere to represent them. Gross! This commit introduces `ErrCode`, an integral newtype for error codes, replacing `String`. It also introduces a constant for every error code, e.g. `E0123`, and removes the `error_code!` macro. The constants are imported wherever used with `use rustc_errors::codes::*`. With the old code, we have three different ways to specify an error code at a use point: ``` error_code!(E0123) // macro call struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call \#[diag(name, code = "E0123")] // string struct Diag; ``` With the new code, they all use the `E0123` constant. ``` E0123 // constant struct_span_code_err!(dcx, span, E0123, "msg"); // constant \#[diag(name, code = E0123)] // constant struct Diag; ``` The commit also changes the structure of the error code definitions: - `rustc_error_codes` now just defines a higher-order macro listing the used error codes and nothing else. - Because that's now the only thing in the `rustc_error_codes` crate, I moved it into the `lib.rs` file and removed the `error_codes.rs` file. - `rustc_errors` uses that macro to define everything, e.g. the error code constants and the `DIAGNOSTIC_TABLES`. This is in its new `codes.rs` file. --- Cargo.lock | 4 +- compiler/rustc_ast_lowering/src/errors.rs | 20 +- compiler/rustc_ast_passes/src/errors.rs | 38 +- .../rustc_attr/src/session_diagnostics.rs | 47 +- .../rustc_borrowck/src/borrowck_errors.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 4 +- .../rustc_borrowck/src/session_diagnostics.rs | 8 +- compiler/rustc_builtin_macros/src/errors.rs | 8 +- compiler/rustc_codegen_ssa/src/back/write.rs | 4 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 2 +- compiler/rustc_codegen_ssa/src/errors.rs | 80 +-- compiler/rustc_const_eval/src/errors.rs | 52 +- .../src/transform/check_consts/ops.rs | 14 +- compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 58 +- compiler/rustc_error_codes/src/error_codes.rs | 658 ----------------- compiler/rustc_error_codes/src/lib.rs | 678 +++++++++++++++++- compiler/rustc_errors/Cargo.toml | 2 + .../src/annotate_snippet_emitter_writer.rs | 7 +- compiler/rustc_errors/src/codes.rs | 39 + compiler/rustc_errors/src/diagnostic.rs | 17 +- .../rustc_errors/src/diagnostic_builder.rs | 13 +- compiler/rustc_errors/src/diagnostic_impls.rs | 3 +- compiler/rustc_errors/src/emitter.rs | 12 +- compiler/rustc_errors/src/json.rs | 4 +- compiler/rustc_errors/src/lib.rs | 19 +- compiler/rustc_errors/src/registry.rs | 9 +- compiler/rustc_expand/src/errors.rs | 11 +- .../rustc_hir_analysis/src/astconv/bounds.rs | 2 +- .../rustc_hir_analysis/src/astconv/errors.rs | 4 +- .../src/astconv/generics.rs | 4 +- .../rustc_hir_analysis/src/astconv/lint.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 10 +- .../src/astconv/object_safety.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 4 +- .../rustc_hir_analysis/src/check/dropck.rs | 2 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../src/coherence/inherent_impls_overlap.rs | 2 +- .../rustc_hir_analysis/src/coherence/mod.rs | 4 +- .../src/coherence/unsafety.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_hir_analysis/src/errors.rs | 140 ++-- .../rustc_hir_analysis/src/impl_wf_check.rs | 2 +- .../src/structured_errors.rs | 6 +- .../missing_cast_for_variadic_arg.rs | 6 +- .../structured_errors/sized_unsized_cast.rs | 6 +- .../wrong_number_of_generic_args.rs | 8 +- compiler/rustc_hir_typeck/src/cast.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 4 +- compiler/rustc_hir_typeck/src/errors.rs | 34 +- compiler/rustc_hir_typeck/src/expr.rs | 12 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 +- compiler/rustc_hir_typeck/src/intrinsicck.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 10 +- .../rustc_hir_typeck/src/method/suggest.rs | 7 +- compiler/rustc_hir_typeck/src/op.rs | 4 +- compiler/rustc_hir_typeck/src/pat.rs | 14 +- compiler/rustc_infer/src/errors/mod.rs | 66 +- .../src/infer/error_reporting/mod.rs | 8 +- .../infer/error_reporting/need_type_info.rs | 12 +- .../infer/error_reporting/note_and_explain.rs | 4 +- .../src/traits/error_reporting/mod.rs | 2 +- compiler/rustc_lint/src/errors.rs | 14 +- compiler/rustc_lint/src/lints.rs | 6 +- .../src/diagnostics/diagnostic_builder.rs | 4 +- compiler/rustc_macros/src/diagnostics/mod.rs | 2 +- compiler/rustc_metadata/src/errors.rs | 28 +- compiler/rustc_middle/src/error.rs | 4 +- compiler/rustc_middle/src/values.rs | 2 +- compiler/rustc_mir_build/src/errors.rs | 64 +- .../src/thir/pattern/check_match.rs | 2 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 4 +- compiler/rustc_mir_transform/src/errors.rs | 6 +- compiler/rustc_parse/src/errors.rs | 18 +- compiler/rustc_parse/src/lexer/mod.rs | 16 +- compiler/rustc_parse/src/parser/attr.rs | 4 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_passes/src/entry.rs | 6 +- compiler/rustc_passes/src/errors.rs | 94 +-- compiler/rustc_privacy/src/errors.rs | 6 +- compiler/rustc_query_system/src/error.rs | 3 +- .../rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 4 +- compiler/rustc_resolve/src/errors.rs | 63 +- compiler/rustc_resolve/src/imports.rs | 2 +- compiler/rustc_resolve/src/late.rs | 54 +- .../rustc_resolve/src/late/diagnostics.rs | 14 +- compiler/rustc_resolve/src/lib.rs | 4 +- compiler/rustc_resolve/src/macros.rs | 2 +- compiler/rustc_session/src/errors.rs | 6 +- compiler/rustc_session/src/session.rs | 6 +- compiler/rustc_trait_selection/src/errors.rs | 20 +- .../traits/error_reporting/infer_ctxt_ext.rs | 2 +- .../error_reporting/on_unimplemented.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 4 +- .../error_reporting/type_err_ctxt_ext.rs | 8 +- .../src/traits/specialize/mod.rs | 4 +- compiler/rustc_ty_utils/src/errors.rs | 3 +- src/librustdoc/clean/mod.rs | 5 +- src/librustdoc/core.rs | 2 +- src/tools/error_index_generator/Cargo.toml | 1 - src/tools/error_index_generator/main.rs | 8 +- src/tools/tidy/src/error_codes.rs | 34 +- .../session-diagnostic/diagnostic-derive.rs | 166 ++--- .../diagnostic-derive.stderr | 268 +++---- .../session-diagnostic/enforce_slug_naming.rs | 2 +- .../enforce_slug_naming.stderr | 2 +- triagebot.toml | 2 +- 110 files changed, 1624 insertions(+), 1572 deletions(-) delete mode 100644 compiler/rustc_error_codes/src/error_codes.rs create mode 100644 compiler/rustc_errors/src/codes.rs diff --git a/Cargo.lock b/Cargo.lock index 454ec90b9afd2..d645957da96af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1268,7 +1268,6 @@ name = "error_index_generator" version = "0.0.0" dependencies = [ "mdbook", - "rustc_error_codes", ] [[package]] @@ -3701,7 +3700,6 @@ dependencies = [ "rustc_codegen_ssa", "rustc_const_eval", "rustc_data_structures", - "rustc_error_codes", "rustc_errors", "rustc_expand", "rustc_feature", @@ -3774,9 +3772,11 @@ dependencies = [ "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", + "rustc_error_codes", "rustc_error_messages", "rustc_fluent_macro", "rustc_hir", + "rustc_index", "rustc_lint_defs", "rustc_macros", "rustc_serialize", diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 4843d36372dcc..51bb8a96fad26 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -1,9 +1,9 @@ -use rustc_errors::DiagnosticArgFromDisplay; +use rustc_errors::{codes::*, DiagnosticArgFromDisplay}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; #[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")] +#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)] pub struct GenericTypeWithParentheses { #[primary_span] #[label] @@ -22,7 +22,7 @@ pub struct UseAngleBrackets { } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_abi, code = "E0703")] +#[diag(ast_lowering_invalid_abi, code = E0703)] #[note] pub struct InvalidAbi { #[primary_span] @@ -89,7 +89,7 @@ pub enum AssocTyParenthesesSub { } #[derive(Diagnostic)] -#[diag(ast_lowering_misplaced_impl_trait, code = "E0562")] +#[diag(ast_lowering_misplaced_impl_trait, code = E0562)] #[note] pub struct MisplacedImplTrait<'a> { #[primary_span] @@ -114,7 +114,7 @@ pub struct UnderscoreExprLhsAssign { } #[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_base_expression_double_dot, code = "E0797")] +#[diag(ast_lowering_base_expression_double_dot, code = E0797)] pub struct BaseExpressionDoubleDot { #[primary_span] #[suggestion(code = "/* expr */", applicability = "has-placeholders", style = "verbose")] @@ -122,7 +122,7 @@ pub struct BaseExpressionDoubleDot { } #[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = "E0728")] +#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)] pub struct AwaitOnlyInAsyncFnAndBlocks { #[primary_span] #[label] @@ -132,14 +132,14 @@ pub struct AwaitOnlyInAsyncFnAndBlocks { } #[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_coroutine_too_many_parameters, code = "E0628")] +#[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)] pub struct CoroutineTooManyParameters { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_closure_cannot_be_static, code = "E0697")] +#[diag(ast_lowering_closure_cannot_be_static, code = E0697)] pub struct ClosureCannotBeStatic { #[primary_span] pub fn_decl_span: Span, @@ -154,14 +154,14 @@ pub struct FunctionalRecordUpdateDestructuringAssignment { } #[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_async_coroutines_not_supported, code = "E0727")] +#[diag(ast_lowering_async_coroutines_not_supported, code = E0727)] pub struct AsyncCoroutinesNotSupported { #[primary_span] pub span: Span, } #[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_inline_asm_unsupported_target, code = "E0472")] +#[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)] pub struct InlineAsmUnsupportedTarget { #[primary_span] pub span: Span, diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index e2b8e64b115e5..5f54a0ddf8c38 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,7 +1,7 @@ //! Errors emitted by ast_passes. use rustc_ast::ParamKindOrd; -use rustc_errors::{AddToDiagnostic, Applicability}; +use rustc_errors::{codes::*, AddToDiagnostic, Applicability}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -23,7 +23,7 @@ pub struct InvalidLabel { } #[derive(Diagnostic)] -#[diag(ast_passes_visibility_not_permitted, code = "E0449")] +#[diag(ast_passes_visibility_not_permitted, code = E0449)] pub struct VisibilityNotPermitted { #[primary_span] pub span: Span, @@ -44,7 +44,7 @@ pub enum VisibilityNotPermittedNote { } #[derive(Diagnostic)] -#[diag(ast_passes_trait_fn_const, code = "E0379")] +#[diag(ast_passes_trait_fn_const, code = E0379)] pub struct TraitFnConst { #[primary_span] #[label] @@ -302,14 +302,14 @@ pub struct ItemUnderscore<'a> { } #[derive(Diagnostic)] -#[diag(ast_passes_nomangle_ascii, code = "E0754")] +#[diag(ast_passes_nomangle_ascii, code = E0754)] pub struct NoMangleAscii { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_module_nonascii, code = "E0754")] +#[diag(ast_passes_module_nonascii, code = E0754)] #[help] pub struct ModuleNonAscii { #[primary_span] @@ -318,7 +318,7 @@ pub struct ModuleNonAscii { } #[derive(Diagnostic)] -#[diag(ast_passes_auto_generic, code = "E0567")] +#[diag(ast_passes_auto_generic, code = E0567)] pub struct AutoTraitGeneric { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] @@ -328,7 +328,7 @@ pub struct AutoTraitGeneric { } #[derive(Diagnostic)] -#[diag(ast_passes_auto_super_lifetime, code = "E0568")] +#[diag(ast_passes_auto_super_lifetime, code = E0568)] pub struct AutoTraitBounds { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] @@ -338,7 +338,7 @@ pub struct AutoTraitBounds { } #[derive(Diagnostic)] -#[diag(ast_passes_auto_items, code = "E0380")] +#[diag(ast_passes_auto_items, code = E0380)] pub struct AutoTraitItems { #[primary_span] pub spans: Vec, @@ -384,28 +384,28 @@ impl AddToDiagnostic for EmptyLabelManySpans { } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_fn_pointer, code = "E0561")] +#[diag(ast_passes_pattern_in_fn_pointer, code = E0561)] pub struct PatternFnPointer { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_trait_object_single_bound, code = "E0226")] +#[diag(ast_passes_trait_object_single_bound, code = E0226)] pub struct TraitObjectBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_impl_trait_path, code = "E0667")] +#[diag(ast_passes_impl_trait_path, code = E0667)] pub struct ImplTraitPath { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_nested_impl_trait, code = "E0666")] +#[diag(ast_passes_nested_impl_trait, code = E0666)] pub struct NestedImplTrait { #[primary_span] pub span: Span, @@ -443,7 +443,7 @@ pub struct ObsoleteAuto { } #[derive(Diagnostic)] -#[diag(ast_passes_unsafe_negative_impl, code = "E0198")] +#[diag(ast_passes_unsafe_negative_impl, code = E0198)] pub struct UnsafeNegativeImpl { #[primary_span] pub span: Span, @@ -468,7 +468,7 @@ pub struct InherentImplCannot<'a> { } #[derive(Diagnostic)] -#[diag(ast_passes_inherent_cannot_be, code = "E0197")] +#[diag(ast_passes_inherent_cannot_be, code = E0197)] pub struct InherentImplCannotUnsafe<'a> { #[primary_span] pub span: Span, @@ -536,7 +536,7 @@ pub struct GenericDefaultTrailing { } #[derive(Diagnostic)] -#[diag(ast_passes_nested_lifetimes, code = "E0316")] +#[diag(ast_passes_nested_lifetimes, code = E0316)] pub struct NestedLifetimes { #[primary_span] pub span: Span, @@ -655,7 +655,7 @@ pub struct ConstAndCVariadic { } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_foreign, code = "E0130")] +#[diag(ast_passes_pattern_in_foreign, code = E0130)] pub struct PatternInForeign { #[primary_span] #[label] @@ -663,7 +663,7 @@ pub struct PatternInForeign { } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_bodiless, code = "E0642")] +#[diag(ast_passes_pattern_in_bodiless, code = E0642)] pub struct PatternInBodiless { #[primary_span] #[label] @@ -711,14 +711,14 @@ pub struct AssociatedSuggestion2 { } #[derive(Diagnostic)] -#[diag(ast_passes_stability_outside_std, code = "E0734")] +#[diag(ast_passes_stability_outside_std, code = E0734)] pub struct StabilityOutsideStd { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_feature_on_non_nightly, code = "E0554")] +#[diag(ast_passes_feature_on_non_nightly, code = E0554)] pub struct FeatureOnNonNightly { #[primary_span] pub span: Span, diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 315a00c8d2fc0..79370602842b0 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -2,8 +2,7 @@ use std::num::IntErrorKind; use rustc_ast as ast; use rustc_errors::{ - error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, - Level, + codes::*, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -12,14 +11,14 @@ use crate::fluent_generated as fluent; use crate::UnsupportedLiteralReason; #[derive(Diagnostic)] -#[diag(attr_expected_one_cfg_pattern, code = "E0536")] +#[diag(attr_expected_one_cfg_pattern, code = E0536)] pub(crate) struct ExpectedOneCfgPattern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_invalid_predicate, code = "E0537")] +#[diag(attr_invalid_predicate, code = E0537)] pub(crate) struct InvalidPredicate { #[primary_span] pub span: Span, @@ -28,7 +27,7 @@ pub(crate) struct InvalidPredicate { } #[derive(Diagnostic)] -#[diag(attr_multiple_item, code = "E0538")] +#[diag(attr_multiple_item, code = E0538)] pub(crate) struct MultipleItem { #[primary_span] pub span: Span, @@ -37,7 +36,7 @@ pub(crate) struct MultipleItem { } #[derive(Diagnostic)] -#[diag(attr_incorrect_meta_item, code = "E0539")] +#[diag(attr_incorrect_meta_item, code = E0539)] pub(crate) struct IncorrectMetaItem { #[primary_span] pub span: Span, @@ -56,7 +55,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> { let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::>(); DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item) .with_span(self.span) - .with_code(error_code!(E0541)) + .with_code(E0541) .with_arg("item", self.item) .with_arg("expected", expected.join(", ")) .with_span_label(self.span, fluent::attr_label) @@ -64,28 +63,28 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> { } #[derive(Diagnostic)] -#[diag(attr_missing_since, code = "E0542")] +#[diag(attr_missing_since, code = E0542)] pub(crate) struct MissingSince { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_missing_note, code = "E0543")] +#[diag(attr_missing_note, code = E0543)] pub(crate) struct MissingNote { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_multiple_stability_levels, code = "E0544")] +#[diag(attr_multiple_stability_levels, code = E0544)] pub(crate) struct MultipleStabilityLevels { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_invalid_issue_string, code = "E0545")] +#[diag(attr_invalid_issue_string, code = E0545)] pub(crate) struct InvalidIssueString { #[primary_span] pub span: Span, @@ -143,21 +142,21 @@ impl InvalidIssueStringCause { } #[derive(Diagnostic)] -#[diag(attr_missing_feature, code = "E0546")] +#[diag(attr_missing_feature, code = E0546)] pub(crate) struct MissingFeature { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_non_ident_feature, code = "E0546")] +#[diag(attr_non_ident_feature, code = E0546)] pub(crate) struct NonIdentFeature { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_missing_issue, code = "E0547")] +#[diag(attr_missing_issue, code = E0547)] pub(crate) struct MissingIssue { #[primary_span] pub span: Span, @@ -166,14 +165,14 @@ pub(crate) struct MissingIssue { // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? // It is more similar to `IncorrectReprFormatGeneric`. #[derive(Diagnostic)] -#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")] +#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)] pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_invalid_repr_hint_no_paren, code = "E0552")] +#[diag(attr_invalid_repr_hint_no_paren, code = E0552)] pub(crate) struct InvalidReprHintNoParen { #[primary_span] pub span: Span, @@ -182,7 +181,7 @@ pub(crate) struct InvalidReprHintNoParen { } #[derive(Diagnostic)] -#[diag(attr_invalid_repr_hint_no_value, code = "E0552")] +#[diag(attr_invalid_repr_hint_no_value, code = E0552)] pub(crate) struct InvalidReprHintNoValue { #[primary_span] pub span: Span, @@ -215,7 +214,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral { }, ); diag.span(self.span); - diag.code(error_code!(E0565)); + diag.code(E0565); if self.is_bytestr { diag.span_suggestion( self.start_point_span, @@ -229,7 +228,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral { } #[derive(Diagnostic)] -#[diag(attr_invalid_repr_align_need_arg, code = "E0589")] +#[diag(attr_invalid_repr_align_need_arg, code = E0589)] pub(crate) struct InvalidReprAlignNeedArg { #[primary_span] #[suggestion(code = "align(...)", applicability = "has-placeholders")] @@ -237,7 +236,7 @@ pub(crate) struct InvalidReprAlignNeedArg { } #[derive(Diagnostic)] -#[diag(attr_invalid_repr_generic, code = "E0589")] +#[diag(attr_invalid_repr_generic, code = E0589)] pub(crate) struct InvalidReprGeneric<'a> { #[primary_span] pub span: Span, @@ -247,14 +246,14 @@ pub(crate) struct InvalidReprGeneric<'a> { } #[derive(Diagnostic)] -#[diag(attr_incorrect_repr_format_align_one_arg, code = "E0693")] +#[diag(attr_incorrect_repr_format_align_one_arg, code = E0693)] pub(crate) struct IncorrectReprFormatAlignOneArg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_incorrect_repr_format_generic, code = "E0693")] +#[diag(attr_incorrect_repr_format_generic, code = E0693)] pub(crate) struct IncorrectReprFormatGeneric<'a> { #[primary_span] pub span: Span, @@ -305,14 +304,14 @@ impl<'a> IncorrectReprFormatGenericCause<'a> { } #[derive(Diagnostic)] -#[diag(attr_rustc_promotable_pairing, code = "E0717")] +#[diag(attr_rustc_promotable_pairing, code = E0717)] pub(crate) struct RustcPromotablePairing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_rustc_allowed_unstable_pairing, code = "E0789")] +#[diag(attr_rustc_allowed_unstable_pairing, code = E0789)] pub(crate) struct RustcAllowedUnstablePairing { #[primary_span] pub span: Span, diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 351976cdaea6b..8a275a8363010 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{struct_span_code_err, DiagCtxt, DiagnosticBuilder}; +use rustc_errors::{codes::*, struct_span_code_err, DiagCtxt, DiagnosticBuilder}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index da67862a48dc9..2e83072b8d132 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3,7 +3,9 @@ use either::Either; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; +use rustc_errors::{ + codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index e321b92603d38..1685624f24772 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -1,4 +1,4 @@ -use rustc_errors::MultiSpan; +use rustc_errors::{codes::*, MultiSpan}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{GenericArg, Ty}; use rustc_span::Span; @@ -6,7 +6,7 @@ use rustc_span::Span; use crate::diagnostics::RegionName; #[derive(Diagnostic)] -#[diag(borrowck_move_unsized, code = "E0161")] +#[diag(borrowck_move_unsized, code = E0161)] pub(crate) struct MoveUnsized<'tcx> { pub ty: Ty<'tcx>, #[primary_span] @@ -281,7 +281,7 @@ pub(crate) enum CaptureVarCause { } #[derive(Diagnostic)] -#[diag(borrowck_cannot_move_when_borrowed, code = "E0505")] +#[diag(borrowck_cannot_move_when_borrowed, code = E0505)] pub(crate) struct MoveBorrow<'a> { pub place: &'a str, pub borrow_place: &'a str, @@ -294,7 +294,7 @@ pub(crate) struct MoveBorrow<'a> { } #[derive(Diagnostic)] -#[diag(borrowck_opaque_type_non_generic_param, code = "E0792")] +#[diag(borrowck_opaque_type_non_generic_param, code = E0792)] pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { pub ty: GenericArg<'tcx>, pub kind: &'a str, diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index d6dfd0efaf913..eadb48ddd36d8 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, - MultiSpan, SingleLabelManySpans, + codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + Level, MultiSpan, SingleLabelManySpans, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -269,7 +269,7 @@ pub(crate) struct ConcatIdentsIdentArgs { } #[derive(Diagnostic)] -#[diag(builtin_macros_bad_derive_target, code = "E0774")] +#[diag(builtin_macros_bad_derive_target, code = E0774)] pub(crate) struct BadDeriveTarget { #[primary_span] #[label] @@ -283,7 +283,7 @@ pub(crate) struct BadDeriveTarget { pub(crate) struct TestsNotSupport {} #[derive(Diagnostic)] -#[diag(builtin_macros_unexpected_lit, code = "E0777")] +#[diag(builtin_macros_unexpected_lit, code = E0777)] pub(crate) struct BadDeriveLit { #[primary_span] #[label] diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 5d497d4a1883a..b13d566b40b3b 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -15,7 +15,7 @@ use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level}; -use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style}; +use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, ErrCode, Style}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ @@ -1000,7 +1000,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>; struct Diagnostic { msgs: Vec<(DiagnosticMessage, Style)>, args: FxHashMap, rustc_errors::DiagnosticArgValue<'static>>, - code: Option, + code: Option, lvl: Level, } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index cca239a43b342..47b1b0801193a 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,6 +1,6 @@ use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; -use rustc_errors::struct_span_code_err; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index f90e1906caf0a..ef291ead190cc 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -4,7 +4,7 @@ use crate::assert_module_sources::CguReuse; use crate::back::command::Command; use crate::fluent_generated as fluent; use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + codes::*, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, IntoDiagnosticArg, Level, }; use rustc_macros::Diagnostic; @@ -612,7 +612,7 @@ pub struct UnknownAtomicOperation; #[derive(Diagnostic)] pub enum InvalidMonomorphization<'tcx> { - #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = E0511)] BasicIntegerType { #[primary_span] span: Span, @@ -620,7 +620,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = E0511)] BasicFloatType { #[primary_span] span: Span, @@ -628,14 +628,14 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = E0511)] FloatToIntUnchecked { #[primary_span] span: Span, ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = E0511)] FloatingPointVector { #[primary_span] span: Span, @@ -644,7 +644,7 @@ pub enum InvalidMonomorphization<'tcx> { in_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = E0511)] FloatingPointType { #[primary_span] span: Span, @@ -652,14 +652,14 @@ pub enum InvalidMonomorphization<'tcx> { in_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = E0511)] UnrecognizedIntrinsic { #[primary_span] span: Span, name: Symbol, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = E0511)] SimdArgument { #[primary_span] span: Span, @@ -667,7 +667,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = E0511)] SimdInput { #[primary_span] span: Span, @@ -675,7 +675,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = E0511)] SimdFirst { #[primary_span] span: Span, @@ -683,7 +683,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = E0511)] SimdSecond { #[primary_span] span: Span, @@ -691,7 +691,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = E0511)] SimdThird { #[primary_span] span: Span, @@ -699,7 +699,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = E0511)] SimdReturn { #[primary_span] span: Span, @@ -707,7 +707,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = E0511)] InvalidBitmask { #[primary_span] span: Span, @@ -717,7 +717,7 @@ pub enum InvalidMonomorphization<'tcx> { expected_bytes: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = E0511)] ReturnLengthInputType { #[primary_span] span: Span, @@ -728,7 +728,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = E0511)] SecondArgumentLength { #[primary_span] span: Span, @@ -739,7 +739,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = E0511)] ThirdArgumentLength { #[primary_span] span: Span, @@ -750,7 +750,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = E0511)] ReturnIntegerType { #[primary_span] span: Span, @@ -759,7 +759,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = E0511)] SimdShuffle { #[primary_span] span: Span, @@ -767,7 +767,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_return_length, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_return_length, code = E0511)] ReturnLength { #[primary_span] span: Span, @@ -777,7 +777,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_element, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_return_element, code = E0511)] ReturnElement { #[primary_span] span: Span, @@ -788,7 +788,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = E0511)] ShuffleIndexNotConstant { #[primary_span] span: Span, @@ -796,7 +796,7 @@ pub enum InvalidMonomorphization<'tcx> { arg_idx: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = E0511)] ShuffleIndexOutOfBounds { #[primary_span] span: Span, @@ -805,7 +805,7 @@ pub enum InvalidMonomorphization<'tcx> { total_len: u128, }, - #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = E0511)] InsertedType { #[primary_span] span: Span, @@ -815,7 +815,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_return_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_return_type, code = E0511)] ReturnType { #[primary_span] span: Span, @@ -825,7 +825,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = E0511)] ExpectedReturnType { #[primary_span] span: Span, @@ -834,7 +834,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = E0511)] MismatchedLengths { #[primary_span] span: Span, @@ -843,7 +843,7 @@ pub enum InvalidMonomorphization<'tcx> { v_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = E0511)] MaskType { #[primary_span] span: Span, @@ -851,7 +851,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = E0511)] VectorArgument { #[primary_span] span: Span, @@ -860,7 +860,7 @@ pub enum InvalidMonomorphization<'tcx> { in_elem: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = E0511)] CannotReturn { #[primary_span] span: Span, @@ -870,7 +870,7 @@ pub enum InvalidMonomorphization<'tcx> { expected_bytes: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = E0511)] ExpectedElementType { #[primary_span] span: Span, @@ -882,7 +882,7 @@ pub enum InvalidMonomorphization<'tcx> { mutability: ExpectedPointerMutability, }, - #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = E0511)] ThirdArgElementType { #[primary_span] span: Span, @@ -891,7 +891,7 @@ pub enum InvalidMonomorphization<'tcx> { third_arg: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = E0511)] UnsupportedSymbolOfSize { #[primary_span] span: Span, @@ -903,7 +903,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = E0511)] UnsupportedSymbol { #[primary_span] span: Span, @@ -914,7 +914,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = E0511)] CastFatPointer { #[primary_span] span: Span, @@ -922,7 +922,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = E0511)] ExpectedPointer { #[primary_span] span: Span, @@ -930,7 +930,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = E0511)] ExpectedUsize { #[primary_span] span: Span, @@ -938,7 +938,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = E0511)] UnsupportedCast { #[primary_span] span: Span, @@ -949,7 +949,7 @@ pub enum InvalidMonomorphization<'tcx> { out_elem: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = E0511)] UnsupportedOperation { #[primary_span] span: Span, @@ -958,7 +958,7 @@ pub enum InvalidMonomorphization<'tcx> { in_elem: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = "E0511")] + #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = E0511)] ExpectedVectorElementType { #[primary_span] span: Span, diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 064d97a49d75a..9e27c19e94cd9 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, - IntoDiagnostic, Level, + codes::*, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, + EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -55,14 +55,14 @@ pub(crate) struct UnstableInStable { } #[derive(Diagnostic)] -#[diag(const_eval_thread_local_access, code = "E0625")] +#[diag(const_eval_thread_local_access, code = E0625)] pub(crate) struct NonConstOpErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_static_access, code = "E0013")] +#[diag(const_eval_static_access, code = E0013)] #[help] pub(crate) struct StaticAccessErr { #[primary_span] @@ -98,7 +98,7 @@ pub(crate) struct PanicNonStrErr { } #[derive(Diagnostic)] -#[diag(const_eval_mut_deref, code = "E0658")] +#[diag(const_eval_mut_deref, code = E0658)] pub(crate) struct MutDerefErr { #[primary_span] pub span: Span, @@ -106,7 +106,7 @@ pub(crate) struct MutDerefErr { } #[derive(Diagnostic)] -#[diag(const_eval_transient_mut_borrow, code = "E0658")] +#[diag(const_eval_transient_mut_borrow, code = E0658)] pub(crate) struct TransientMutBorrowErr { #[primary_span] pub span: Span, @@ -114,7 +114,7 @@ pub(crate) struct TransientMutBorrowErr { } #[derive(Diagnostic)] -#[diag(const_eval_transient_mut_raw, code = "E0658")] +#[diag(const_eval_transient_mut_raw, code = E0658)] pub(crate) struct TransientMutRawErr { #[primary_span] pub span: Span, @@ -146,7 +146,7 @@ pub(crate) struct UnstableConstFn { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_mutable_refs, code = "E0764")] +#[diag(const_eval_unallowed_mutable_refs, code = E0764)] pub(crate) struct UnallowedMutableRefs { #[primary_span] pub span: Span, @@ -156,7 +156,7 @@ pub(crate) struct UnallowedMutableRefs { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_mutable_raw, code = "E0764")] +#[diag(const_eval_unallowed_mutable_raw, code = E0764)] pub(crate) struct UnallowedMutableRaw { #[primary_span] pub span: Span, @@ -165,7 +165,7 @@ pub(crate) struct UnallowedMutableRaw { pub teach: Option<()>, } #[derive(Diagnostic)] -#[diag(const_eval_non_const_fmt_macro_call, code = "E0015")] +#[diag(const_eval_non_const_fmt_macro_call, code = E0015)] pub(crate) struct NonConstFmtMacroCall { #[primary_span] pub span: Span, @@ -173,7 +173,7 @@ pub(crate) struct NonConstFmtMacroCall { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_fn_call, code = "E0015")] +#[diag(const_eval_non_const_fn_call, code = E0015)] pub(crate) struct NonConstFnCall { #[primary_span] pub span: Span, @@ -190,7 +190,7 @@ pub(crate) struct UnallowedOpInConstContext { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_heap_allocations, code = "E0010")] +#[diag(const_eval_unallowed_heap_allocations, code = E0010)] pub(crate) struct UnallowedHeapAllocations { #[primary_span] #[label] @@ -201,7 +201,7 @@ pub(crate) struct UnallowedHeapAllocations { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_inline_asm, code = "E0015")] +#[diag(const_eval_unallowed_inline_asm, code = E0015)] pub(crate) struct UnallowedInlineAsm { #[primary_span] pub span: Span, @@ -209,7 +209,7 @@ pub(crate) struct UnallowedInlineAsm { } #[derive(Diagnostic)] -#[diag(const_eval_interior_mutable_data_refer, code = "E0492")] +#[diag(const_eval_interior_mutable_data_refer, code = E0492)] pub(crate) struct InteriorMutableDataRefer { #[primary_span] #[label] @@ -274,7 +274,7 @@ pub struct RawBytesNote { // FIXME(fee1-dead) do not use stringly typed `ConstContext` #[derive(Diagnostic)] -#[diag(const_eval_match_eq_non_const, code = "E0015")] +#[diag(const_eval_match_eq_non_const, code = E0015)] #[note] pub struct NonConstMatchEq<'tcx> { #[primary_span] @@ -284,7 +284,7 @@ pub struct NonConstMatchEq<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_for_loop_into_iter_non_const, code = "E0015")] +#[diag(const_eval_for_loop_into_iter_non_const, code = E0015)] pub struct NonConstForLoopIntoIter<'tcx> { #[primary_span] pub span: Span, @@ -293,7 +293,7 @@ pub struct NonConstForLoopIntoIter<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_question_branch_non_const, code = "E0015")] +#[diag(const_eval_question_branch_non_const, code = E0015)] pub struct NonConstQuestionBranch<'tcx> { #[primary_span] pub span: Span, @@ -302,7 +302,7 @@ pub struct NonConstQuestionBranch<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_question_from_residual_non_const, code = "E0015")] +#[diag(const_eval_question_from_residual_non_const, code = E0015)] pub struct NonConstQuestionFromResidual<'tcx> { #[primary_span] pub span: Span, @@ -311,7 +311,7 @@ pub struct NonConstQuestionFromResidual<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_try_block_from_output_non_const, code = "E0015")] +#[diag(const_eval_try_block_from_output_non_const, code = E0015)] pub struct NonConstTryBlockFromOutput<'tcx> { #[primary_span] pub span: Span, @@ -320,7 +320,7 @@ pub struct NonConstTryBlockFromOutput<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_await_non_const, code = "E0015")] +#[diag(const_eval_await_non_const, code = E0015)] pub struct NonConstAwait<'tcx> { #[primary_span] pub span: Span, @@ -329,7 +329,7 @@ pub struct NonConstAwait<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_closure_non_const, code = "E0015")] +#[diag(const_eval_closure_non_const, code = E0015)] pub struct NonConstClosure { #[primary_span] pub span: Span, @@ -362,7 +362,7 @@ pub struct ConsiderDereferencing { } #[derive(Diagnostic)] -#[diag(const_eval_operator_non_const, code = "E0015")] +#[diag(const_eval_operator_non_const, code = E0015)] pub struct NonConstOperator { #[primary_span] pub span: Span, @@ -372,7 +372,7 @@ pub struct NonConstOperator { } #[derive(Diagnostic)] -#[diag(const_eval_deref_coercion_non_const, code = "E0015")] +#[diag(const_eval_deref_coercion_non_const, code = E0015)] #[note] pub struct NonConstDerefCoercion<'tcx> { #[primary_span] @@ -385,7 +385,7 @@ pub struct NonConstDerefCoercion<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_live_drop, code = "E0493")] +#[diag(const_eval_live_drop, code = E0493)] pub struct LiveDrop<'tcx> { #[primary_span] #[label] @@ -397,7 +397,7 @@ pub struct LiveDrop<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_error, code = "E0080")] +#[diag(const_eval_error, code = E0080)] pub struct ConstEvalError { #[primary_span] pub span: Span, @@ -423,7 +423,7 @@ pub struct NullaryIntrinsicError { } #[derive(Diagnostic)] -#[diag(const_eval_undefined_behavior, code = "E0080")] +#[diag(const_eval_undefined_behavior, code = E0080)] pub struct UndefinedBehavior { #[primary_span] pub span: Span, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 39bc2b960e9f5..fb705d91977d7 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -2,7 +2,7 @@ use hir::def_id::LocalDefId; use hir::{ConstContext, LangItem}; -use rustc_errors::{error_code, DiagnosticBuilder}; +use rustc_errors::{codes::*, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -372,7 +372,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation { ccx.dcx().create_err(errors::UnallowedHeapAllocations { span, kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()), + teach: ccx.tcx.sess.teach(E0010).then_some(()), }) } } @@ -434,14 +434,14 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow { span, opt_help: Some(()), kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()), + teach: ccx.tcx.sess.teach(E0492).then_some(()), }) } else { ccx.dcx().create_err(errors::InteriorMutableDataRefer { span, opt_help: None, kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()), + teach: ccx.tcx.sess.teach(E0492).then_some(()), }) } } @@ -469,12 +469,12 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow { hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw { span, kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()), + teach: ccx.tcx.sess.teach(E0764).then_some(()), }), hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs { span, kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()), + teach: ccx.tcx.sess.teach(E0764).then_some(()), }), } } @@ -588,7 +588,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess { ccx.dcx().create_err(errors::StaticAccessErr { span, kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(&error_code!(E0013)).then_some(()), + teach: ccx.tcx.sess.teach(E0013).then_some(()), }) } } diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 97a7dfef3b395..bfdd871455c94 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -15,7 +15,6 @@ rustc_builtin_macros = { path = "../rustc_builtin_macros" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } -rustc_error_codes = { path = "../rustc_error_codes" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 09e627fa7a359..5903c43ae98af 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -23,9 +23,8 @@ use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults}; use rustc_data_structures::profiling::{ get_resident_set_size, print_time_passes_entry, TimePassesFormat, }; -use rustc_errors::registry::{InvalidErrorCode, Registry}; -use rustc_errors::{markdown, ColorConfig}; -use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult}; +use rustc_errors::registry::Registry; +use rustc_errors::{markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, PResult}; use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; @@ -207,7 +206,7 @@ impl Callbacks for TimePassesCallbacks { } pub fn diagnostics_registry() -> Registry { - Registry::new(rustc_error_codes::DIAGNOSTICS) + Registry::new(rustc_errors::codes::DIAGNOSTICS) } /// This is the primary entry point for rustc. @@ -535,37 +534,36 @@ pub enum Compilation { } fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, color: ColorConfig) { + // Allow "E0123" or "0123" form. let upper_cased_code = code.to_ascii_uppercase(); - let normalised = - if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") }; - match registry.try_find_description(&normalised) { - Ok(description) => { - let mut is_in_code_block = false; - let mut text = String::new(); - // Slice off the leading newline and print. - for line in description.lines() { - let indent_level = - line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len()); - let dedented_line = &line[indent_level..]; - if dedented_line.starts_with("```") { - is_in_code_block = !is_in_code_block; - text.push_str(&line[..(indent_level + 3)]); - } else if is_in_code_block && dedented_line.starts_with("# ") { - continue; - } else { - text.push_str(line); - } - text.push('\n'); - } - if io::stdout().is_terminal() { - show_md_content_with_pager(&text, color); + let start = if upper_cased_code.starts_with('E') { 1 } else { 0 }; + if let Ok(code) = upper_cased_code[start..].parse::() + && let Ok(description) = registry.try_find_description(ErrCode::from_u32(code)) + { + let mut is_in_code_block = false; + let mut text = String::new(); + // Slice off the leading newline and print. + for line in description.lines() { + let indent_level = + line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len()); + let dedented_line = &line[indent_level..]; + if dedented_line.starts_with("```") { + is_in_code_block = !is_in_code_block; + text.push_str(&line[..(indent_level + 3)]); + } else if is_in_code_block && dedented_line.starts_with("# ") { + continue; } else { - safe_print!("{text}"); + text.push_str(line); } + text.push('\n'); } - Err(InvalidErrorCode) => { - early_dcx.early_fatal(format!("{code} is not a valid error code")); + if io::stdout().is_terminal() { + show_md_content_with_pager(&text, color); + } else { + safe_print!("{text}"); } + } else { + early_dcx.early_fatal(format!("{code} is not a valid error code")); } } diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs deleted file mode 100644 index 9cd9ed54d4146..0000000000000 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ /dev/null @@ -1,658 +0,0 @@ -// Error messages for EXXXX errors. Each message should start and end with a -// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and -// use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -// -// /!\ IMPORTANT /!\ -// -// Error messages' format must follow the RFC 1567 available here: -// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html - -register_diagnostics! { -E0001: include_str!("./error_codes/E0001.md"), -E0002: include_str!("./error_codes/E0002.md"), -E0004: include_str!("./error_codes/E0004.md"), -E0005: include_str!("./error_codes/E0005.md"), -E0007: include_str!("./error_codes/E0007.md"), -E0009: include_str!("./error_codes/E0009.md"), -E0010: include_str!("./error_codes/E0010.md"), -E0013: include_str!("./error_codes/E0013.md"), -E0014: include_str!("./error_codes/E0014.md"), -E0015: include_str!("./error_codes/E0015.md"), -E0023: include_str!("./error_codes/E0023.md"), -E0025: include_str!("./error_codes/E0025.md"), -E0026: include_str!("./error_codes/E0026.md"), -E0027: include_str!("./error_codes/E0027.md"), -E0029: include_str!("./error_codes/E0029.md"), -E0030: include_str!("./error_codes/E0030.md"), -E0033: include_str!("./error_codes/E0033.md"), -E0034: include_str!("./error_codes/E0034.md"), -E0038: include_str!("./error_codes/E0038.md"), -E0040: include_str!("./error_codes/E0040.md"), -E0044: include_str!("./error_codes/E0044.md"), -E0045: include_str!("./error_codes/E0045.md"), -E0046: include_str!("./error_codes/E0046.md"), -E0049: include_str!("./error_codes/E0049.md"), -E0050: include_str!("./error_codes/E0050.md"), -E0053: include_str!("./error_codes/E0053.md"), -E0054: include_str!("./error_codes/E0054.md"), -E0055: include_str!("./error_codes/E0055.md"), -E0057: include_str!("./error_codes/E0057.md"), -E0059: include_str!("./error_codes/E0059.md"), -E0060: include_str!("./error_codes/E0060.md"), -E0061: include_str!("./error_codes/E0061.md"), -E0062: include_str!("./error_codes/E0062.md"), -E0063: include_str!("./error_codes/E0063.md"), -E0067: include_str!("./error_codes/E0067.md"), -E0069: include_str!("./error_codes/E0069.md"), -E0070: include_str!("./error_codes/E0070.md"), -E0071: include_str!("./error_codes/E0071.md"), -E0072: include_str!("./error_codes/E0072.md"), -E0073: include_str!("./error_codes/E0073.md"), -E0074: include_str!("./error_codes/E0074.md"), -E0075: include_str!("./error_codes/E0075.md"), -E0076: include_str!("./error_codes/E0076.md"), -E0077: include_str!("./error_codes/E0077.md"), -E0080: include_str!("./error_codes/E0080.md"), -E0081: include_str!("./error_codes/E0081.md"), -E0084: include_str!("./error_codes/E0084.md"), -E0087: include_str!("./error_codes/E0087.md"), -E0088: include_str!("./error_codes/E0088.md"), -E0089: include_str!("./error_codes/E0089.md"), -E0090: include_str!("./error_codes/E0090.md"), -E0091: include_str!("./error_codes/E0091.md"), -E0092: include_str!("./error_codes/E0092.md"), -E0093: include_str!("./error_codes/E0093.md"), -E0094: include_str!("./error_codes/E0094.md"), -E0106: include_str!("./error_codes/E0106.md"), -E0107: include_str!("./error_codes/E0107.md"), -E0109: include_str!("./error_codes/E0109.md"), -E0110: include_str!("./error_codes/E0110.md"), -E0116: include_str!("./error_codes/E0116.md"), -E0117: include_str!("./error_codes/E0117.md"), -E0118: include_str!("./error_codes/E0118.md"), -E0119: include_str!("./error_codes/E0119.md"), -E0120: include_str!("./error_codes/E0120.md"), -E0121: include_str!("./error_codes/E0121.md"), -E0124: include_str!("./error_codes/E0124.md"), -E0128: include_str!("./error_codes/E0128.md"), -E0130: include_str!("./error_codes/E0130.md"), -E0131: include_str!("./error_codes/E0131.md"), -E0132: include_str!("./error_codes/E0132.md"), -E0133: include_str!("./error_codes/E0133.md"), -E0136: include_str!("./error_codes/E0136.md"), -E0137: include_str!("./error_codes/E0137.md"), -E0138: include_str!("./error_codes/E0138.md"), -E0139: include_str!("./error_codes/E0139.md"), -E0152: include_str!("./error_codes/E0152.md"), -E0154: include_str!("./error_codes/E0154.md"), -E0158: include_str!("./error_codes/E0158.md"), -E0161: include_str!("./error_codes/E0161.md"), -E0162: include_str!("./error_codes/E0162.md"), -E0164: include_str!("./error_codes/E0164.md"), -E0165: include_str!("./error_codes/E0165.md"), -E0170: include_str!("./error_codes/E0170.md"), -E0178: include_str!("./error_codes/E0178.md"), -E0183: include_str!("./error_codes/E0183.md"), -E0184: include_str!("./error_codes/E0184.md"), -E0185: include_str!("./error_codes/E0185.md"), -E0186: include_str!("./error_codes/E0186.md"), -E0191: include_str!("./error_codes/E0191.md"), -E0192: include_str!("./error_codes/E0192.md"), -E0193: include_str!("./error_codes/E0193.md"), -E0195: include_str!("./error_codes/E0195.md"), -E0197: include_str!("./error_codes/E0197.md"), -E0198: include_str!("./error_codes/E0198.md"), -E0199: include_str!("./error_codes/E0199.md"), -E0200: include_str!("./error_codes/E0200.md"), -E0201: include_str!("./error_codes/E0201.md"), -E0203: include_str!("./error_codes/E0203.md"), -E0204: include_str!("./error_codes/E0204.md"), -E0205: include_str!("./error_codes/E0205.md"), -E0206: include_str!("./error_codes/E0206.md"), -E0207: include_str!("./error_codes/E0207.md"), -E0208: include_str!("./error_codes/E0208.md"), -E0210: include_str!("./error_codes/E0210.md"), -E0211: include_str!("./error_codes/E0211.md"), -E0212: include_str!("./error_codes/E0212.md"), -E0214: include_str!("./error_codes/E0214.md"), -E0220: include_str!("./error_codes/E0220.md"), -E0221: include_str!("./error_codes/E0221.md"), -E0222: include_str!("./error_codes/E0222.md"), -E0223: include_str!("./error_codes/E0223.md"), -E0224: include_str!("./error_codes/E0224.md"), -E0225: include_str!("./error_codes/E0225.md"), -E0226: include_str!("./error_codes/E0226.md"), -E0227: include_str!("./error_codes/E0227.md"), -E0228: include_str!("./error_codes/E0228.md"), -E0229: include_str!("./error_codes/E0229.md"), -E0230: include_str!("./error_codes/E0230.md"), -E0231: include_str!("./error_codes/E0231.md"), -E0232: include_str!("./error_codes/E0232.md"), -E0243: include_str!("./error_codes/E0243.md"), -E0244: include_str!("./error_codes/E0244.md"), -E0251: include_str!("./error_codes/E0251.md"), -E0252: include_str!("./error_codes/E0252.md"), -E0253: include_str!("./error_codes/E0253.md"), -E0254: include_str!("./error_codes/E0254.md"), -E0255: include_str!("./error_codes/E0255.md"), -E0256: include_str!("./error_codes/E0256.md"), -E0259: include_str!("./error_codes/E0259.md"), -E0260: include_str!("./error_codes/E0260.md"), -E0261: include_str!("./error_codes/E0261.md"), -E0262: include_str!("./error_codes/E0262.md"), -E0263: include_str!("./error_codes/E0263.md"), -E0264: include_str!("./error_codes/E0264.md"), -E0267: include_str!("./error_codes/E0267.md"), -E0268: include_str!("./error_codes/E0268.md"), -E0271: include_str!("./error_codes/E0271.md"), -E0275: include_str!("./error_codes/E0275.md"), -E0276: include_str!("./error_codes/E0276.md"), -E0277: include_str!("./error_codes/E0277.md"), -E0281: include_str!("./error_codes/E0281.md"), -E0282: include_str!("./error_codes/E0282.md"), -E0283: include_str!("./error_codes/E0283.md"), -E0284: include_str!("./error_codes/E0284.md"), -E0297: include_str!("./error_codes/E0297.md"), -E0301: include_str!("./error_codes/E0301.md"), -E0302: include_str!("./error_codes/E0302.md"), -E0303: include_str!("./error_codes/E0303.md"), -E0307: include_str!("./error_codes/E0307.md"), -E0308: include_str!("./error_codes/E0308.md"), -E0309: include_str!("./error_codes/E0309.md"), -E0310: include_str!("./error_codes/E0310.md"), -E0311: include_str!("./error_codes/E0311.md"), -E0312: include_str!("./error_codes/E0312.md"), -E0316: include_str!("./error_codes/E0316.md"), -E0317: include_str!("./error_codes/E0317.md"), -E0320: include_str!("./error_codes/E0320.md"), -E0321: include_str!("./error_codes/E0321.md"), -E0322: include_str!("./error_codes/E0322.md"), -E0323: include_str!("./error_codes/E0323.md"), -E0324: include_str!("./error_codes/E0324.md"), -E0325: include_str!("./error_codes/E0325.md"), -E0326: include_str!("./error_codes/E0326.md"), -E0328: include_str!("./error_codes/E0328.md"), -E0329: include_str!("./error_codes/E0329.md"), -E0364: include_str!("./error_codes/E0364.md"), -E0365: include_str!("./error_codes/E0365.md"), -E0366: include_str!("./error_codes/E0366.md"), -E0367: include_str!("./error_codes/E0367.md"), -E0368: include_str!("./error_codes/E0368.md"), -E0369: include_str!("./error_codes/E0369.md"), -E0370: include_str!("./error_codes/E0370.md"), -E0371: include_str!("./error_codes/E0371.md"), -E0373: include_str!("./error_codes/E0373.md"), -E0374: include_str!("./error_codes/E0374.md"), -E0375: include_str!("./error_codes/E0375.md"), -E0376: include_str!("./error_codes/E0376.md"), -E0377: include_str!("./error_codes/E0377.md"), -E0378: include_str!("./error_codes/E0378.md"), -E0379: include_str!("./error_codes/E0379.md"), -E0380: include_str!("./error_codes/E0380.md"), -E0381: include_str!("./error_codes/E0381.md"), -E0382: include_str!("./error_codes/E0382.md"), -E0383: include_str!("./error_codes/E0383.md"), -E0384: include_str!("./error_codes/E0384.md"), -E0386: include_str!("./error_codes/E0386.md"), -E0387: include_str!("./error_codes/E0387.md"), -E0388: include_str!("./error_codes/E0388.md"), -E0389: include_str!("./error_codes/E0389.md"), -E0390: include_str!("./error_codes/E0390.md"), -E0391: include_str!("./error_codes/E0391.md"), -E0392: include_str!("./error_codes/E0392.md"), -E0393: include_str!("./error_codes/E0393.md"), -E0398: include_str!("./error_codes/E0398.md"), -E0399: include_str!("./error_codes/E0399.md"), -E0401: include_str!("./error_codes/E0401.md"), -E0403: include_str!("./error_codes/E0403.md"), -E0404: include_str!("./error_codes/E0404.md"), -E0405: include_str!("./error_codes/E0405.md"), -E0407: include_str!("./error_codes/E0407.md"), -E0408: include_str!("./error_codes/E0408.md"), -E0409: include_str!("./error_codes/E0409.md"), -E0411: include_str!("./error_codes/E0411.md"), -E0412: include_str!("./error_codes/E0412.md"), -E0415: include_str!("./error_codes/E0415.md"), -E0416: include_str!("./error_codes/E0416.md"), -E0422: include_str!("./error_codes/E0422.md"), -E0423: include_str!("./error_codes/E0423.md"), -E0424: include_str!("./error_codes/E0424.md"), -E0425: include_str!("./error_codes/E0425.md"), -E0426: include_str!("./error_codes/E0426.md"), -E0428: include_str!("./error_codes/E0428.md"), -E0429: include_str!("./error_codes/E0429.md"), -E0430: include_str!("./error_codes/E0430.md"), -E0431: include_str!("./error_codes/E0431.md"), -E0432: include_str!("./error_codes/E0432.md"), -E0433: include_str!("./error_codes/E0433.md"), -E0434: include_str!("./error_codes/E0434.md"), -E0435: include_str!("./error_codes/E0435.md"), -E0436: include_str!("./error_codes/E0436.md"), -E0437: include_str!("./error_codes/E0437.md"), -E0438: include_str!("./error_codes/E0438.md"), -E0439: include_str!("./error_codes/E0439.md"), -E0445: include_str!("./error_codes/E0445.md"), -E0446: include_str!("./error_codes/E0446.md"), -E0447: include_str!("./error_codes/E0447.md"), -E0448: include_str!("./error_codes/E0448.md"), -E0449: include_str!("./error_codes/E0449.md"), -E0451: include_str!("./error_codes/E0451.md"), -E0452: include_str!("./error_codes/E0452.md"), -E0453: include_str!("./error_codes/E0453.md"), -E0454: include_str!("./error_codes/E0454.md"), -E0455: include_str!("./error_codes/E0455.md"), -E0457: include_str!("./error_codes/E0457.md"), -E0458: include_str!("./error_codes/E0458.md"), -E0459: include_str!("./error_codes/E0459.md"), -E0460: include_str!("./error_codes/E0460.md"), -E0461: include_str!("./error_codes/E0461.md"), -E0462: include_str!("./error_codes/E0462.md"), -E0463: include_str!("./error_codes/E0463.md"), -E0464: include_str!("./error_codes/E0464.md"), -E0466: include_str!("./error_codes/E0466.md"), -E0468: include_str!("./error_codes/E0468.md"), -E0469: include_str!("./error_codes/E0469.md"), -E0472: include_str!("./error_codes/E0472.md"), -E0476: include_str!("./error_codes/E0476.md"), -E0477: include_str!("./error_codes/E0477.md"), -E0478: include_str!("./error_codes/E0478.md"), -E0482: include_str!("./error_codes/E0482.md"), -E0491: include_str!("./error_codes/E0491.md"), -E0492: include_str!("./error_codes/E0492.md"), -E0493: include_str!("./error_codes/E0493.md"), -E0495: include_str!("./error_codes/E0495.md"), -E0496: include_str!("./error_codes/E0496.md"), -E0497: include_str!("./error_codes/E0497.md"), -E0498: include_str!("./error_codes/E0498.md"), -E0499: include_str!("./error_codes/E0499.md"), -E0500: include_str!("./error_codes/E0500.md"), -E0501: include_str!("./error_codes/E0501.md"), -E0502: include_str!("./error_codes/E0502.md"), -E0503: include_str!("./error_codes/E0503.md"), -E0504: include_str!("./error_codes/E0504.md"), -E0505: include_str!("./error_codes/E0505.md"), -E0506: include_str!("./error_codes/E0506.md"), -E0507: include_str!("./error_codes/E0507.md"), -E0508: include_str!("./error_codes/E0508.md"), -E0509: include_str!("./error_codes/E0509.md"), -E0510: include_str!("./error_codes/E0510.md"), -E0511: include_str!("./error_codes/E0511.md"), -E0512: include_str!("./error_codes/E0512.md"), -E0514: include_str!("./error_codes/E0514.md"), -E0515: include_str!("./error_codes/E0515.md"), -E0516: include_str!("./error_codes/E0516.md"), -E0517: include_str!("./error_codes/E0517.md"), -E0518: include_str!("./error_codes/E0518.md"), -E0519: include_str!("./error_codes/E0519.md"), -E0520: include_str!("./error_codes/E0520.md"), -E0521: include_str!("./error_codes/E0521.md"), -E0522: include_str!("./error_codes/E0522.md"), -E0523: include_str!("./error_codes/E0523.md"), -E0524: include_str!("./error_codes/E0524.md"), -E0525: include_str!("./error_codes/E0525.md"), -E0527: include_str!("./error_codes/E0527.md"), -E0528: include_str!("./error_codes/E0528.md"), -E0529: include_str!("./error_codes/E0529.md"), -E0530: include_str!("./error_codes/E0530.md"), -E0531: include_str!("./error_codes/E0531.md"), -E0532: include_str!("./error_codes/E0532.md"), -E0533: include_str!("./error_codes/E0533.md"), -E0534: include_str!("./error_codes/E0534.md"), -E0535: include_str!("./error_codes/E0535.md"), -E0536: include_str!("./error_codes/E0536.md"), -E0537: include_str!("./error_codes/E0537.md"), -E0538: include_str!("./error_codes/E0538.md"), -E0539: include_str!("./error_codes/E0539.md"), -E0541: include_str!("./error_codes/E0541.md"), -E0542: include_str!("./error_codes/E0542.md"), -E0543: include_str!("./error_codes/E0543.md"), -E0544: include_str!("./error_codes/E0544.md"), -E0545: include_str!("./error_codes/E0545.md"), -E0546: include_str!("./error_codes/E0546.md"), -E0547: include_str!("./error_codes/E0547.md"), -E0549: include_str!("./error_codes/E0549.md"), -E0550: include_str!("./error_codes/E0550.md"), -E0551: include_str!("./error_codes/E0551.md"), -E0552: include_str!("./error_codes/E0552.md"), -E0554: include_str!("./error_codes/E0554.md"), -E0556: include_str!("./error_codes/E0556.md"), -E0557: include_str!("./error_codes/E0557.md"), -E0559: include_str!("./error_codes/E0559.md"), -E0560: include_str!("./error_codes/E0560.md"), -E0561: include_str!("./error_codes/E0561.md"), -E0562: include_str!("./error_codes/E0562.md"), -E0565: include_str!("./error_codes/E0565.md"), -E0566: include_str!("./error_codes/E0566.md"), -E0567: include_str!("./error_codes/E0567.md"), -E0568: include_str!("./error_codes/E0568.md"), -E0569: include_str!("./error_codes/E0569.md"), -E0570: include_str!("./error_codes/E0570.md"), -E0571: include_str!("./error_codes/E0571.md"), -E0572: include_str!("./error_codes/E0572.md"), -E0573: include_str!("./error_codes/E0573.md"), -E0574: include_str!("./error_codes/E0574.md"), -E0575: include_str!("./error_codes/E0575.md"), -E0576: include_str!("./error_codes/E0576.md"), -E0577: include_str!("./error_codes/E0577.md"), -E0578: include_str!("./error_codes/E0578.md"), -E0579: include_str!("./error_codes/E0579.md"), -E0580: include_str!("./error_codes/E0580.md"), -E0581: include_str!("./error_codes/E0581.md"), -E0582: include_str!("./error_codes/E0582.md"), -E0583: include_str!("./error_codes/E0583.md"), -E0584: include_str!("./error_codes/E0584.md"), -E0585: include_str!("./error_codes/E0585.md"), -E0586: include_str!("./error_codes/E0586.md"), -E0587: include_str!("./error_codes/E0587.md"), -E0588: include_str!("./error_codes/E0588.md"), -E0589: include_str!("./error_codes/E0589.md"), -E0590: include_str!("./error_codes/E0590.md"), -E0591: include_str!("./error_codes/E0591.md"), -E0592: include_str!("./error_codes/E0592.md"), -E0593: include_str!("./error_codes/E0593.md"), -E0594: include_str!("./error_codes/E0594.md"), -E0595: include_str!("./error_codes/E0595.md"), -E0596: include_str!("./error_codes/E0596.md"), -E0597: include_str!("./error_codes/E0597.md"), -E0599: include_str!("./error_codes/E0599.md"), -E0600: include_str!("./error_codes/E0600.md"), -E0601: include_str!("./error_codes/E0601.md"), -E0602: include_str!("./error_codes/E0602.md"), -E0603: include_str!("./error_codes/E0603.md"), -E0604: include_str!("./error_codes/E0604.md"), -E0605: include_str!("./error_codes/E0605.md"), -E0606: include_str!("./error_codes/E0606.md"), -E0607: include_str!("./error_codes/E0607.md"), -E0608: include_str!("./error_codes/E0608.md"), -E0609: include_str!("./error_codes/E0609.md"), -E0610: include_str!("./error_codes/E0610.md"), -E0614: include_str!("./error_codes/E0614.md"), -E0615: include_str!("./error_codes/E0615.md"), -E0616: include_str!("./error_codes/E0616.md"), -E0617: include_str!("./error_codes/E0617.md"), -E0618: include_str!("./error_codes/E0618.md"), -E0619: include_str!("./error_codes/E0619.md"), -E0620: include_str!("./error_codes/E0620.md"), -E0621: include_str!("./error_codes/E0621.md"), -E0622: include_str!("./error_codes/E0622.md"), -E0623: include_str!("./error_codes/E0623.md"), -E0624: include_str!("./error_codes/E0624.md"), -E0625: include_str!("./error_codes/E0625.md"), -E0626: include_str!("./error_codes/E0626.md"), -E0627: include_str!("./error_codes/E0627.md"), -E0628: include_str!("./error_codes/E0628.md"), -E0631: include_str!("./error_codes/E0631.md"), -E0632: include_str!("./error_codes/E0632.md"), -E0633: include_str!("./error_codes/E0633.md"), -E0634: include_str!("./error_codes/E0634.md"), -E0635: include_str!("./error_codes/E0635.md"), -E0636: include_str!("./error_codes/E0636.md"), -E0637: include_str!("./error_codes/E0637.md"), -E0638: include_str!("./error_codes/E0638.md"), -E0639: include_str!("./error_codes/E0639.md"), -E0640: include_str!("./error_codes/E0640.md"), -E0641: include_str!("./error_codes/E0641.md"), -E0642: include_str!("./error_codes/E0642.md"), -E0643: include_str!("./error_codes/E0643.md"), -E0644: include_str!("./error_codes/E0644.md"), -E0646: include_str!("./error_codes/E0646.md"), -E0647: include_str!("./error_codes/E0647.md"), -E0648: include_str!("./error_codes/E0648.md"), -E0657: include_str!("./error_codes/E0657.md"), -E0658: include_str!("./error_codes/E0658.md"), -E0659: include_str!("./error_codes/E0659.md"), -E0660: include_str!("./error_codes/E0660.md"), -E0661: include_str!("./error_codes/E0661.md"), -E0662: include_str!("./error_codes/E0662.md"), -E0663: include_str!("./error_codes/E0663.md"), -E0664: include_str!("./error_codes/E0664.md"), -E0665: include_str!("./error_codes/E0665.md"), -E0666: include_str!("./error_codes/E0666.md"), -E0667: include_str!("./error_codes/E0667.md"), -E0668: include_str!("./error_codes/E0668.md"), -E0669: include_str!("./error_codes/E0669.md"), -E0670: include_str!("./error_codes/E0670.md"), -E0671: include_str!("./error_codes/E0671.md"), -E0687: include_str!("./error_codes/E0687.md"), -E0688: include_str!("./error_codes/E0688.md"), -E0689: include_str!("./error_codes/E0689.md"), -E0690: include_str!("./error_codes/E0690.md"), -E0691: include_str!("./error_codes/E0691.md"), -E0692: include_str!("./error_codes/E0692.md"), -E0693: include_str!("./error_codes/E0693.md"), -E0695: include_str!("./error_codes/E0695.md"), -E0696: include_str!("./error_codes/E0696.md"), -E0697: include_str!("./error_codes/E0697.md"), -E0698: include_str!("./error_codes/E0698.md"), -E0699: include_str!("./error_codes/E0699.md"), -E0700: include_str!("./error_codes/E0700.md"), -E0701: include_str!("./error_codes/E0701.md"), -E0703: include_str!("./error_codes/E0703.md"), -E0704: include_str!("./error_codes/E0704.md"), -E0705: include_str!("./error_codes/E0705.md"), -E0706: include_str!("./error_codes/E0706.md"), -E0708: include_str!("./error_codes/E0708.md"), -E0710: include_str!("./error_codes/E0710.md"), -E0712: include_str!("./error_codes/E0712.md"), -E0713: include_str!("./error_codes/E0713.md"), -E0714: include_str!("./error_codes/E0714.md"), -E0715: include_str!("./error_codes/E0715.md"), -E0716: include_str!("./error_codes/E0716.md"), -E0711: include_str!("./error_codes/E0711.md"), -E0717: include_str!("./error_codes/E0717.md"), -E0718: include_str!("./error_codes/E0718.md"), -E0719: include_str!("./error_codes/E0719.md"), -E0720: include_str!("./error_codes/E0720.md"), -E0722: include_str!("./error_codes/E0722.md"), -E0724: include_str!("./error_codes/E0724.md"), -E0725: include_str!("./error_codes/E0725.md"), -E0726: include_str!("./error_codes/E0726.md"), -E0727: include_str!("./error_codes/E0727.md"), -E0728: include_str!("./error_codes/E0728.md"), -E0729: include_str!("./error_codes/E0729.md"), -E0730: include_str!("./error_codes/E0730.md"), -E0731: include_str!("./error_codes/E0731.md"), -E0732: include_str!("./error_codes/E0732.md"), -E0733: include_str!("./error_codes/E0733.md"), -E0734: include_str!("./error_codes/E0734.md"), -E0735: include_str!("./error_codes/E0735.md"), -E0736: include_str!("./error_codes/E0736.md"), -E0737: include_str!("./error_codes/E0737.md"), -E0739: include_str!("./error_codes/E0739.md"), -E0740: include_str!("./error_codes/E0740.md"), -E0741: include_str!("./error_codes/E0741.md"), -E0742: include_str!("./error_codes/E0742.md"), -E0743: include_str!("./error_codes/E0743.md"), -E0744: include_str!("./error_codes/E0744.md"), -E0745: include_str!("./error_codes/E0745.md"), -E0746: include_str!("./error_codes/E0746.md"), -E0747: include_str!("./error_codes/E0747.md"), -E0748: include_str!("./error_codes/E0748.md"), -E0749: include_str!("./error_codes/E0749.md"), -E0750: include_str!("./error_codes/E0750.md"), -E0751: include_str!("./error_codes/E0751.md"), -E0752: include_str!("./error_codes/E0752.md"), -E0753: include_str!("./error_codes/E0753.md"), -E0754: include_str!("./error_codes/E0754.md"), -E0755: include_str!("./error_codes/E0755.md"), -E0756: include_str!("./error_codes/E0756.md"), -E0757: include_str!("./error_codes/E0757.md"), -E0758: include_str!("./error_codes/E0758.md"), -E0759: include_str!("./error_codes/E0759.md"), -E0760: include_str!("./error_codes/E0760.md"), -E0761: include_str!("./error_codes/E0761.md"), -E0762: include_str!("./error_codes/E0762.md"), -E0763: include_str!("./error_codes/E0763.md"), -E0764: include_str!("./error_codes/E0764.md"), -E0765: include_str!("./error_codes/E0765.md"), -E0766: include_str!("./error_codes/E0766.md"), -E0767: include_str!("./error_codes/E0767.md"), -E0768: include_str!("./error_codes/E0768.md"), -E0769: include_str!("./error_codes/E0769.md"), -E0770: include_str!("./error_codes/E0770.md"), -E0771: include_str!("./error_codes/E0771.md"), -E0772: include_str!("./error_codes/E0772.md"), -E0773: include_str!("./error_codes/E0773.md"), -E0774: include_str!("./error_codes/E0774.md"), -E0775: include_str!("./error_codes/E0775.md"), -E0776: include_str!("./error_codes/E0776.md"), -E0777: include_str!("./error_codes/E0777.md"), -E0778: include_str!("./error_codes/E0778.md"), -E0779: include_str!("./error_codes/E0779.md"), -E0780: include_str!("./error_codes/E0780.md"), -E0781: include_str!("./error_codes/E0781.md"), -E0782: include_str!("./error_codes/E0782.md"), -E0783: include_str!("./error_codes/E0783.md"), -E0784: include_str!("./error_codes/E0784.md"), -E0785: include_str!("./error_codes/E0785.md"), -E0786: include_str!("./error_codes/E0786.md"), -E0787: include_str!("./error_codes/E0787.md"), -E0788: include_str!("./error_codes/E0788.md"), -E0789: include_str!("./error_codes/E0789.md"), -E0790: include_str!("./error_codes/E0790.md"), -E0791: include_str!("./error_codes/E0791.md"), -E0792: include_str!("./error_codes/E0792.md"), -E0793: include_str!("./error_codes/E0793.md"), -E0794: include_str!("./error_codes/E0794.md"), -E0795: include_str!("./error_codes/E0795.md"), -E0796: include_str!("./error_codes/E0796.md"), -E0797: include_str!("./error_codes/E0797.md"), -} - -// Undocumented removed error codes. Note that many removed error codes are kept in the list above -// and marked as no-longer emitted with a note in the markdown file (see E0001 for an example). -// E0006, // merged with E0005 -// E0008, // cannot bind by-move into a pattern guard -// E0019, // merged into E0015 -// E0035, // merged into E0087/E0089 -// E0036, // merged into E0087/E0089 -// E0068, -// E0085, -// E0086, -// E0101, // replaced with E0282 -// E0102, // replaced with E0282 -// E0103, -// E0104, -// E0122, // bounds in type aliases are ignored, turned into proper lint -// E0123, -// E0127, -// E0129, -// E0134, -// E0135, -// E0141, -// E0153, // unused error code -// E0157, // unused error code -// E0159, // use of trait `{}` as struct constructor -// E0163, // merged into E0071 -// E0167, -// E0168, -// E0172, // non-trait found in a type sum, moved to resolve -// E0173, // manual implementations of unboxed closure traits are experimental -// E0174, -// E0182, // merged into E0229 -// E0187, // cannot infer the kind of the closure -// E0188, // can not cast an immutable reference to a mutable pointer -// E0189, // deprecated: can only cast a boxed pointer to a boxed object -// E0190, // deprecated: can only cast a &-pointer to an &-object -// E0194, // merged into E0403 -// E0196, // cannot determine a type for this closure -// E0209, // builtin traits can only be implemented on structs or enums -// E0213, // associated types are not accepted in this context -// E0215, // angle-bracket notation is not stable with `Fn` -// E0216, // parenthetical notation is only stable with `Fn` -// E0217, // ambiguous associated type, defined in multiple supertraits -// E0218, // no associated type defined -// E0219, // associated type defined in higher-ranked supertrait -// E0233, -// E0234, -// E0235, // structure constructor specifies a structure of type but -// E0236, // no lang item for range syntax -// E0237, // no lang item for range syntax -// E0238, // parenthesized parameters may only be used with a trait -// E0239, // `next` method of `Iterator` trait has unexpected type -// E0240, -// E0241, -// E0242, -// E0245, // not a trait -// E0246, // invalid recursive type -// E0247, -// E0248, // value used as a type, now reported earlier during resolution -// // as E0412 -// E0249, -// E0257, -// E0258, -// E0272, // on_unimplemented #0 -// E0273, // on_unimplemented #1 -// E0274, // on_unimplemented #2 -// E0278, // requirement is not satisfied -// E0279, -// E0280, // changed to ICE -// E0285, // overflow evaluation builtin bounds -// E0296, // replaced with a generic attribute input check -// E0298, // cannot compare constants -// E0299, // mismatched types between arms -// E0300, // unexpanded macro -// E0304, // expected signed integer constant -// E0305, // expected constant -// E0313, // removed: found unreachable -// E0314, // closure outlives stack frame -// E0315, // cannot invoke closure outside of its lifetime -// E0319, // trait impls for defaulted traits allowed just for structs/enums -// E0372, // coherence not object safe -// E0385, // {} in an aliasable location -// E0402, // cannot use an outer type parameter in this context -// E0406, // merged into 420 -// E0410, // merged into 408 -// E0413, // merged into 530 -// E0414, // merged into 530 -// E0417, // merged into 532 -// E0418, // merged into 532 -// E0419, // merged into 531 -// E0420, // merged into 532 -// E0421, // merged into 531 -// E0427, // merged into 530 -// E0445, // merged into 446 and type privacy lints -// E0456, // plugin `..` is not available for triple `..` -// E0465, // removed: merged with E0464 -// E0467, // removed -// E0470, // removed -// E0471, // constant evaluation error (in pattern) -// E0473, // dereference of reference outside its lifetime -// E0474, // captured variable `..` does not outlive the enclosing closure -// E0475, // index of slice outside its lifetime -// E0479, // the type `..` (provided as the value of a type parameter) is... -// E0480, // lifetime of method receiver does not outlive the method call -// E0481, // lifetime of function argument does not outlive the function call -// E0483, // lifetime of operand does not outlive the operation -// E0484, // reference is not valid at the time of borrow -// E0485, // automatically reference is not valid at the time of borrow -// E0486, // type of expression contains references that are not valid during.. -// E0487, // unsafe use of destructor: destructor might be called while... -// E0488, // lifetime of variable does not enclose its declaration -// E0489, // type/lifetime parameter not in scope here -// E0490, // removed: unreachable -// E0526, // shuffle indices are not constant -// E0540, // multiple rustc_deprecated attributes -// E0548, // replaced with a generic attribute input check -// E0553, // multiple rustc_const_unstable attributes -// E0555, // replaced with a generic attribute input check -// E0558, // replaced with a generic attribute input check -// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 -// E0564, // only named lifetimes are allowed in `impl Trait`, -// // but `{}` was found in the type `{}` -// E0598, // lifetime of {} is too short to guarantee its contents can be... -// E0611, // merged into E0616 -// E0612, // merged into E0609 -// E0613, // Removed (merged with E0609) -// E0629, // missing 'feature' (rustc_const_unstable) -// E0630, // rustc_const_unstable attribute must be paired with stable/unstable -// // attribute -// E0645, // trait aliases not finished -// E0694, // an unknown tool name found in scoped attributes -// E0702, // replaced with a generic attribute input check -// E0707, // multiple elided lifetimes used in arguments of `async fn` -// E0709, // multiple different lifetimes used in arguments of `async fn` -// E0721, // `await` keyword -// E0723, // unstable feature in `const` context -// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. -// E0744, // merged into E0728 diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index dd2818116368b..5b2766618fccb 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -1,19 +1,679 @@ +//! This library is used to gather all error codes into one place, to make +//! their maintenance easier. + #![allow(internal_features)] #![feature(rustdoc_internals)] #![doc(rust_logo)] #![deny(rustdoc::invalid_codeblock_attributes)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -//! This library is used to gather all error codes into one place, -//! the goal being to make their maintenance easier. -macro_rules! register_diagnostics { - ($($ecode:ident: $message:expr,)*) => ( - pub static DIAGNOSTICS: &[(&str, &str)] = &[ - $( (stringify!($ecode), $message), )* - ]; +// This higher-order macro defines the error codes that are in use. It is used +// in the `rustc_errors` crate. Removed error codes are listed in the comment +// below. +// +// /!\ IMPORTANT /!\ +// +// Error code explanation are defined in `error_codes/EXXXX.md` files. They must follow the RFC +// 1567 available here: +// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html +// +// Also, the contents of this macro is checked by tidy (in `check_error_codes_docs`). If you change +// the macro syntax you will need to change tidy as well. +// +// Both columns are necessary because it's not possible in Rust to create a new identifier such as +// `E0123` from an integer literal such as `0123`, unfortunately. +#[macro_export] +macro_rules! error_codes { + ($macro:path) => ( + $macro!( +E0001: 0001, +E0002: 0002, +E0004: 0004, +E0005: 0005, +E0007: 0007, +E0009: 0009, +E0010: 0010, +E0013: 0013, +E0014: 0014, +E0015: 0015, +E0023: 0023, +E0025: 0025, +E0026: 0026, +E0027: 0027, +E0029: 0029, +E0030: 0030, +E0033: 0033, +E0034: 0034, +E0038: 0038, +E0040: 0040, +E0044: 0044, +E0045: 0045, +E0046: 0046, +E0049: 0049, +E0050: 0050, +E0053: 0053, +E0054: 0054, +E0055: 0055, +E0057: 0057, +E0059: 0059, +E0060: 0060, +E0061: 0061, +E0062: 0062, +E0063: 0063, +E0067: 0067, +E0069: 0069, +E0070: 0070, +E0071: 0071, +E0072: 0072, +E0073: 0073, +E0074: 0074, +E0075: 0075, +E0076: 0076, +E0077: 0077, +E0080: 0080, +E0081: 0081, +E0084: 0084, +E0087: 0087, +E0088: 0088, +E0089: 0089, +E0090: 0090, +E0091: 0091, +E0092: 0092, +E0093: 0093, +E0094: 0094, +E0106: 0106, +E0107: 0107, +E0109: 0109, +E0110: 0110, +E0116: 0116, +E0117: 0117, +E0118: 0118, +E0119: 0119, +E0120: 0120, +E0121: 0121, +E0124: 0124, +E0128: 0128, +E0130: 0130, +E0131: 0131, +E0132: 0132, +E0133: 0133, +E0136: 0136, +E0137: 0137, +E0138: 0138, +E0139: 0139, +E0152: 0152, +E0154: 0154, +E0158: 0158, +E0161: 0161, +E0162: 0162, +E0164: 0164, +E0165: 0165, +E0170: 0170, +E0178: 0178, +E0183: 0183, +E0184: 0184, +E0185: 0185, +E0186: 0186, +E0191: 0191, +E0192: 0192, +E0193: 0193, +E0195: 0195, +E0197: 0197, +E0198: 0198, +E0199: 0199, +E0200: 0200, +E0201: 0201, +E0203: 0203, +E0204: 0204, +E0205: 0205, +E0206: 0206, +E0207: 0207, +E0208: 0208, +E0210: 0210, +E0211: 0211, +E0212: 0212, +E0214: 0214, +E0220: 0220, +E0221: 0221, +E0222: 0222, +E0223: 0223, +E0224: 0224, +E0225: 0225, +E0226: 0226, +E0227: 0227, +E0228: 0228, +E0229: 0229, +E0230: 0230, +E0231: 0231, +E0232: 0232, +E0243: 0243, +E0244: 0244, +E0251: 0251, +E0252: 0252, +E0253: 0253, +E0254: 0254, +E0255: 0255, +E0256: 0256, +E0259: 0259, +E0260: 0260, +E0261: 0261, +E0262: 0262, +E0263: 0263, +E0264: 0264, +E0267: 0267, +E0268: 0268, +E0271: 0271, +E0275: 0275, +E0276: 0276, +E0277: 0277, +E0281: 0281, +E0282: 0282, +E0283: 0283, +E0284: 0284, +E0297: 0297, +E0301: 0301, +E0302: 0302, +E0303: 0303, +E0307: 0307, +E0308: 0308, +E0309: 0309, +E0310: 0310, +E0311: 0311, +E0312: 0312, +E0316: 0316, +E0317: 0317, +E0320: 0320, +E0321: 0321, +E0322: 0322, +E0323: 0323, +E0324: 0324, +E0325: 0325, +E0326: 0326, +E0328: 0328, +E0329: 0329, +E0364: 0364, +E0365: 0365, +E0366: 0366, +E0367: 0367, +E0368: 0368, +E0369: 0369, +E0370: 0370, +E0371: 0371, +E0373: 0373, +E0374: 0374, +E0375: 0375, +E0376: 0376, +E0377: 0377, +E0378: 0378, +E0379: 0379, +E0380: 0380, +E0381: 0381, +E0382: 0382, +E0383: 0383, +E0384: 0384, +E0386: 0386, +E0387: 0387, +E0388: 0388, +E0389: 0389, +E0390: 0390, +E0391: 0391, +E0392: 0392, +E0393: 0393, +E0398: 0398, +E0399: 0399, +E0401: 0401, +E0403: 0403, +E0404: 0404, +E0405: 0405, +E0407: 0407, +E0408: 0408, +E0409: 0409, +E0411: 0411, +E0412: 0412, +E0415: 0415, +E0416: 0416, +E0422: 0422, +E0423: 0423, +E0424: 0424, +E0425: 0425, +E0426: 0426, +E0428: 0428, +E0429: 0429, +E0430: 0430, +E0431: 0431, +E0432: 0432, +E0433: 0433, +E0434: 0434, +E0435: 0435, +E0436: 0436, +E0437: 0437, +E0438: 0438, +E0439: 0439, +E0445: 0445, +E0446: 0446, +E0447: 0447, +E0448: 0448, +E0449: 0449, +E0451: 0451, +E0452: 0452, +E0453: 0453, +E0454: 0454, +E0455: 0455, +E0457: 0457, +E0458: 0458, +E0459: 0459, +E0460: 0460, +E0461: 0461, +E0462: 0462, +E0463: 0463, +E0464: 0464, +E0466: 0466, +E0468: 0468, +E0469: 0469, +E0472: 0472, +E0476: 0476, +E0477: 0477, +E0478: 0478, +E0482: 0482, +E0491: 0491, +E0492: 0492, +E0493: 0493, +E0495: 0495, +E0496: 0496, +E0497: 0497, +E0498: 0498, +E0499: 0499, +E0500: 0500, +E0501: 0501, +E0502: 0502, +E0503: 0503, +E0504: 0504, +E0505: 0505, +E0506: 0506, +E0507: 0507, +E0508: 0508, +E0509: 0509, +E0510: 0510, +E0511: 0511, +E0512: 0512, +E0514: 0514, +E0515: 0515, +E0516: 0516, +E0517: 0517, +E0518: 0518, +E0519: 0519, +E0520: 0520, +E0521: 0521, +E0522: 0522, +E0523: 0523, +E0524: 0524, +E0525: 0525, +E0527: 0527, +E0528: 0528, +E0529: 0529, +E0530: 0530, +E0531: 0531, +E0532: 0532, +E0533: 0533, +E0534: 0534, +E0535: 0535, +E0536: 0536, +E0537: 0537, +E0538: 0538, +E0539: 0539, +E0541: 0541, +E0542: 0542, +E0543: 0543, +E0544: 0544, +E0545: 0545, +E0546: 0546, +E0547: 0547, +E0549: 0549, +E0550: 0550, +E0551: 0551, +E0552: 0552, +E0554: 0554, +E0556: 0556, +E0557: 0557, +E0559: 0559, +E0560: 0560, +E0561: 0561, +E0562: 0562, +E0565: 0565, +E0566: 0566, +E0567: 0567, +E0568: 0568, +E0569: 0569, +E0570: 0570, +E0571: 0571, +E0572: 0572, +E0573: 0573, +E0574: 0574, +E0575: 0575, +E0576: 0576, +E0577: 0577, +E0578: 0578, +E0579: 0579, +E0580: 0580, +E0581: 0581, +E0582: 0582, +E0583: 0583, +E0584: 0584, +E0585: 0585, +E0586: 0586, +E0587: 0587, +E0588: 0588, +E0589: 0589, +E0590: 0590, +E0591: 0591, +E0592: 0592, +E0593: 0593, +E0594: 0594, +E0595: 0595, +E0596: 0596, +E0597: 0597, +E0599: 0599, +E0600: 0600, +E0601: 0601, +E0602: 0602, +E0603: 0603, +E0604: 0604, +E0605: 0605, +E0606: 0606, +E0607: 0607, +E0608: 0608, +E0609: 0609, +E0610: 0610, +E0614: 0614, +E0615: 0615, +E0616: 0616, +E0617: 0617, +E0618: 0618, +E0619: 0619, +E0620: 0620, +E0621: 0621, +E0622: 0622, +E0623: 0623, +E0624: 0624, +E0625: 0625, +E0626: 0626, +E0627: 0627, +E0628: 0628, +E0631: 0631, +E0632: 0632, +E0633: 0633, +E0634: 0634, +E0635: 0635, +E0636: 0636, +E0637: 0637, +E0638: 0638, +E0639: 0639, +E0640: 0640, +E0641: 0641, +E0642: 0642, +E0643: 0643, +E0644: 0644, +E0646: 0646, +E0647: 0647, +E0648: 0648, +E0657: 0657, +E0658: 0658, +E0659: 0659, +E0660: 0660, +E0661: 0661, +E0662: 0662, +E0663: 0663, +E0664: 0664, +E0665: 0665, +E0666: 0666, +E0667: 0667, +E0668: 0668, +E0669: 0669, +E0670: 0670, +E0671: 0671, +E0687: 0687, +E0688: 0688, +E0689: 0689, +E0690: 0690, +E0691: 0691, +E0692: 0692, +E0693: 0693, +E0695: 0695, +E0696: 0696, +E0697: 0697, +E0698: 0698, +E0699: 0699, +E0700: 0700, +E0701: 0701, +E0703: 0703, +E0704: 0704, +E0705: 0705, +E0706: 0706, +E0708: 0708, +E0710: 0710, +E0712: 0712, +E0713: 0713, +E0714: 0714, +E0715: 0715, +E0716: 0716, +E0711: 0711, +E0717: 0717, +E0718: 0718, +E0719: 0719, +E0720: 0720, +E0722: 0722, +E0724: 0724, +E0725: 0725, +E0726: 0726, +E0727: 0727, +E0728: 0728, +E0729: 0729, +E0730: 0730, +E0731: 0731, +E0732: 0732, +E0733: 0733, +E0734: 0734, +E0735: 0735, +E0736: 0736, +E0737: 0737, +E0739: 0739, +E0740: 0740, +E0741: 0741, +E0742: 0742, +E0743: 0743, +E0744: 0744, +E0745: 0745, +E0746: 0746, +E0747: 0747, +E0748: 0748, +E0749: 0749, +E0750: 0750, +E0751: 0751, +E0752: 0752, +E0753: 0753, +E0754: 0754, +E0755: 0755, +E0756: 0756, +E0757: 0757, +E0758: 0758, +E0759: 0759, +E0760: 0760, +E0761: 0761, +E0762: 0762, +E0763: 0763, +E0764: 0764, +E0765: 0765, +E0766: 0766, +E0767: 0767, +E0768: 0768, +E0769: 0769, +E0770: 0770, +E0771: 0771, +E0772: 0772, +E0773: 0773, +E0774: 0774, +E0775: 0775, +E0776: 0776, +E0777: 0777, +E0778: 0778, +E0779: 0779, +E0780: 0780, +E0781: 0781, +E0782: 0782, +E0783: 0783, +E0784: 0784, +E0785: 0785, +E0786: 0786, +E0787: 0787, +E0788: 0788, +E0789: 0789, +E0790: 0790, +E0791: 0791, +E0792: 0792, +E0793: 0793, +E0794: 0794, +E0795: 0795, +E0796: 0796, +E0797: 0797, + ); ) } -mod error_codes; -pub use error_codes::DIAGNOSTICS; +// Undocumented removed error codes. Note that many removed error codes are kept in the list above +// and marked as no-longer emitted with a note in the markdown file (see E0001 for an example). +// E0006, // merged with E0005 +// E0008, // cannot bind by-move into a pattern guard +// E0019, // merged into E0015 +// E0035, // merged into E0087/E0089 +// E0036, // merged into E0087/E0089 +// E0068, +// E0085, +// E0086, +// E0101, // replaced with E0282 +// E0102, // replaced with E0282 +// E0103, +// E0104, +// E0122, // bounds in type aliases are ignored, turned into proper lint +// E0123, +// E0127, +// E0129, +// E0134, +// E0135, +// E0141, +// E0153, // unused error code +// E0157, // unused error code +// E0159, // use of trait `{}` as struct constructor +// E0163, // merged into E0071 +// E0167, +// E0168, +// E0172, // non-trait found in a type sum, moved to resolve +// E0173, // manual implementations of unboxed closure traits are experimental +// E0174, +// E0182, // merged into E0229 +// E0187, // cannot infer the kind of the closure +// E0188, // can not cast an immutable reference to a mutable pointer +// E0189, // deprecated: can only cast a boxed pointer to a boxed object +// E0190, // deprecated: can only cast a &-pointer to an &-object +// E0194, // merged into E0403 +// E0196, // cannot determine a type for this closure +// E0209, // builtin traits can only be implemented on structs or enums +// E0213, // associated types are not accepted in this context +// E0215, // angle-bracket notation is not stable with `Fn` +// E0216, // parenthetical notation is only stable with `Fn` +// E0217, // ambiguous associated type, defined in multiple supertraits +// E0218, // no associated type defined +// E0219, // associated type defined in higher-ranked supertrait +// E0233, +// E0234, +// E0235, // structure constructor specifies a structure of type but +// E0236, // no lang item for range syntax +// E0237, // no lang item for range syntax +// E0238, // parenthesized parameters may only be used with a trait +// E0239, // `next` method of `Iterator` trait has unexpected type +// E0240, +// E0241, +// E0242, +// E0245, // not a trait +// E0246, // invalid recursive type +// E0247, +// E0248, // value used as a type, now reported earlier during resolution +// // as E0412 +// E0249, +// E0257, +// E0258, +// E0272, // on_unimplemented #0 +// E0273, // on_unimplemented #1 +// E0274, // on_unimplemented #2 +// E0278, // requirement is not satisfied +// E0279, +// E0280, // changed to ICE +// E0285, // overflow evaluation builtin bounds +// E0296, // replaced with a generic attribute input check +// E0298, // cannot compare constants +// E0299, // mismatched types between arms +// E0300, // unexpanded macro +// E0304, // expected signed integer constant +// E0305, // expected constant +// E0313, // removed: found unreachable +// E0314, // closure outlives stack frame +// E0315, // cannot invoke closure outside of its lifetime +// E0319, // trait impls for defaulted traits allowed just for structs/enums +// E0372, // coherence not object safe +// E0385, // {} in an aliasable location +// E0402, // cannot use an outer type parameter in this context +// E0406, // merged into 420 +// E0410, // merged into 408 +// E0413, // merged into 530 +// E0414, // merged into 530 +// E0417, // merged into 532 +// E0418, // merged into 532 +// E0419, // merged into 531 +// E0420, // merged into 532 +// E0421, // merged into 531 +// E0427, // merged into 530 +// E0445, // merged into 446 and type privacy lints +// E0456, // plugin `..` is not available for triple `..` +// E0465, // removed: merged with E0464 +// E0467, // removed +// E0470, // removed +// E0471, // constant evaluation error (in pattern) +// E0473, // dereference of reference outside its lifetime +// E0474, // captured variable `..` does not outlive the enclosing closure +// E0475, // index of slice outside its lifetime +// E0479, // the type `..` (provided as the value of a type parameter) is... +// E0480, // lifetime of method receiver does not outlive the method call +// E0481, // lifetime of function argument does not outlive the function call +// E0483, // lifetime of operand does not outlive the operation +// E0484, // reference is not valid at the time of borrow +// E0485, // automatically reference is not valid at the time of borrow +// E0486, // type of expression contains references that are not valid during.. +// E0487, // unsafe use of destructor: destructor might be called while... +// E0488, // lifetime of variable does not enclose its declaration +// E0489, // type/lifetime parameter not in scope here +// E0490, // removed: unreachable +// E0526, // shuffle indices are not constant +// E0540, // multiple rustc_deprecated attributes +// E0548, // replaced with a generic attribute input check +// E0553, // multiple rustc_const_unstable attributes +// E0555, // replaced with a generic attribute input check +// E0558, // replaced with a generic attribute input check +// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 +// E0564, // only named lifetimes are allowed in `impl Trait`, +// // but `{}` was found in the type `{}` +// E0598, // lifetime of {} is too short to guarantee its contents can be... +// E0611, // merged into E0616 +// E0612, // merged into E0609 +// E0613, // Removed (merged with E0609) +// E0629, // missing 'feature' (rustc_const_unstable) +// E0630, // rustc_const_unstable attribute must be paired with stable/unstable +// // attribute +// E0645, // trait aliases not finished +// E0694, // an unknown tool name found in scoped attributes +// E0702, // replaced with a generic attribute input check +// E0707, // multiple elided lifetimes used in arguments of `async fn` +// E0709, // multiple different lifetimes used in arguments of `async fn` +// E0721, // `await` keyword +// E0723, // unstable feature in `const` context +// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. +// E0744, // merged into E0728 diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 0c1fcecb57173..a2d1fd2a92419 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -10,9 +10,11 @@ derive_setters = "0.1.6" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_error_codes = { path = "../rustc_error_codes" } rustc_error_messages = { path = "../rustc_error_messages" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f0699a56f98ef..949f52ef6b586 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines; use crate::snippet::Line; use crate::translation::{to_fluent_args, Translate}; use crate::{ - CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle, - Level, MultiSpan, Style, SubDiagnostic, + CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, ErrCode, FluentBundle, + LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic, }; use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use rustc_data_structures::sync::Lrc; @@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter { level: &Level, messages: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, msp: &MultiSpan, _children: &[SubDiagnostic], _suggestions: &[CodeSuggestion], @@ -178,6 +178,7 @@ impl AnnotateSnippetEmitter { .collect::>() }) .collect(); + let code = code.map(|code| code.to_string()); let snippet = Snippet { title: Some(Annotation { label: Some(&message), diff --git a/compiler/rustc_errors/src/codes.rs b/compiler/rustc_errors/src/codes.rs new file mode 100644 index 0000000000000..947cf27ca7957 --- /dev/null +++ b/compiler/rustc_errors/src/codes.rs @@ -0,0 +1,39 @@ +//! This module defines the following. +//! - The `ErrCode` type. +//! - A constant for every error code, with a name like `E0123`. +//! - A static table `DIAGNOSTICS` pairing every error code constant with its +//! long description text. + +use std::fmt; + +rustc_index::newtype_index! { + #[max = 9999] // Because all error codes have four digits. + #[orderable] + #[encodable] + #[debug_format = "ErrCode({})"] + pub struct ErrCode {} +} + +impl fmt::Display for ErrCode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "E{:04}", self.as_u32()) + } +} + +macro_rules! define_error_code_constants_and_diagnostics_table { + ($($name:ident: $num:literal,)*) => ( + $( + pub const $name: $crate::ErrCode = $crate::ErrCode::from_u32($num); + )* + pub static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[ + $( ( + $name, + include_str!( + concat!("../../rustc_error_codes/src/error_codes/", stringify!($name), ".md") + ) + ), )* + ]; + ) +} + +rustc_error_codes::error_codes!(define_error_code_constants_and_diagnostics_table); diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 4934bc2450c79..8a32e29ddc9dc 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,7 +1,8 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, - MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, + CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, + ErrCode, Level, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, + SuggestionStyle, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_error_messages::fluent_value_from_str_list_sep_by_and; @@ -104,7 +105,7 @@ pub struct Diagnostic { pub(crate) level: Level, pub messages: Vec<(DiagnosticMessage, Style)>, - pub code: Option, + pub code: Option, pub span: MultiSpan, pub children: Vec, pub suggestions: Result, SuggestionsDisabled>, @@ -893,8 +894,8 @@ impl Diagnostic { self } - pub fn code(&mut self, s: String) -> &mut Self { - self.code = Some(s); + pub fn code(&mut self, code: ErrCode) -> &mut Self { + self.code = Some(code); self } @@ -903,8 +904,8 @@ impl Diagnostic { self } - pub fn get_code(&self) -> Option<&str> { - self.code.as_deref() + pub fn get_code(&self) -> Option { + self.code } pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { @@ -990,7 +991,7 @@ impl Diagnostic { &Level, &[(DiagnosticMessage, Style)], Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>, - &Option, + &Option, &Option, &MultiSpan, &Result, SuggestionsDisabled>, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 87e2d295c7f4c..8bfb181648628 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -1,7 +1,7 @@ use crate::diagnostic::IntoDiagnosticArg; use crate::{DiagCtxt, Level, MultiSpan, StashKey}; use crate::{ - Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug, + Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrCode, ErrorGuaranteed, ExplicitBug, SubdiagnosticMessage, }; use rustc_lint_defs::Applicability; @@ -399,7 +399,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { name: String, has_future_breakage: bool, )); forward!((code, with_code)( - s: String, + code: ErrCode, )); forward!((arg, with_arg)( name: impl Into>, arg: impl IntoDiagnosticArg, @@ -439,12 +439,7 @@ impl Drop for DiagnosticBuilder<'_, G> { #[macro_export] macro_rules! struct_span_code_err { - ($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - $dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code)) + ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({ + $dcx.struct_span_err($span, format!($($message)*)).with_code($code) }) } - -#[macro_export] -macro_rules! error_code { - ($code:ident) => {{ stringify!($code).to_owned() }}; -} diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index d58d05095cdcb..df3fd4af4b436 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -1,7 +1,7 @@ use crate::diagnostic::DiagnosticLocation; use crate::{fluent_generated as fluent, AddToDiagnostic}; use crate::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic, IntoDiagnosticArg, Level, }; use rustc_ast as ast; @@ -93,6 +93,7 @@ into_diagnostic_arg_using_display!( &TargetTriple, SplitDebuginfo, ExitStatus, + ErrCode, ); into_diagnostic_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 23efdaea0ebb8..9f76c1dd248b0 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -17,8 +17,8 @@ use crate::styled_buffer::StyledBuffer; use crate::translation::{to_fluent_args, Translate}; use crate::{ diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage, - FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, - SuggestionStyle, TerminalUrl, + ErrCode, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, + SubstitutionHighlight, SuggestionStyle, TerminalUrl, }; use rustc_lint_defs::pluralize; @@ -1309,7 +1309,7 @@ impl HumanEmitter { msp: &MultiSpan, msgs: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, level: &Level, max_line_num_len: usize, is_secondary: bool, @@ -1340,9 +1340,9 @@ impl HumanEmitter { buffer.append(0, "[", Style::Level(*level)); let code = if let TerminalUrl::Yes = self.terminal_url { let path = "https://doc.rust-lang.org/error_codes"; - Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")) + format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07") } else { - Cow::Borrowed(code) + code.to_string() }; buffer.append(0, &code, Style::Level(*level)); buffer.append(0, "]", Style::Level(*level)); @@ -2076,7 +2076,7 @@ impl HumanEmitter { level: &Level, messages: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, span: &MultiSpan, children: &[SubDiagnostic], suggestions: &[CodeSuggestion], diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 51b064f4c617a..6f92299827950 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -400,10 +400,10 @@ impl Diagnostic { let translated_message = je.translate_messages(&diag.messages, &args); - let code = if let Some(code) = &diag.code { + let code = if let Some(code) = diag.code { Some(DiagnosticCode { code: code.to_string(), - explanation: je.registry.as_ref().unwrap().try_find_description(&code).ok(), + explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(), }) } else if let Some(IsLint { name, .. }) = &diag.is_lint { Some(DiagnosticCode { code: name.to_string(), explanation: None }) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a64ad2beb6c54..6d9208341a5c0 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -14,6 +14,7 @@ #![feature(error_reporter)] #![feature(extract_if)] #![feature(let_chains)] +#![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] @@ -30,6 +31,7 @@ extern crate tracing; extern crate self as rustc_errors; +pub use codes::*; pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, @@ -78,6 +80,7 @@ use std::path::{Path, PathBuf}; use Level::*; pub mod annotate_snippet_emitter_writer; +pub mod codes; mod diagnostic; mod diagnostic_builder; mod diagnostic_impls; @@ -446,10 +449,10 @@ struct DiagCtxtInner { /// This set contains the code of all emitted diagnostics to avoid /// emitting the same diagnostic with extended help (`--teach`) twice, which /// would be unnecessary repetition. - taught_diagnostics: FxHashSet, + taught_diagnostics: FxHashSet, /// Used to suggest rustc --explain `` - emitted_diagnostic_codes: FxIndexSet, + emitted_diagnostic_codes: FxIndexSet, /// This set contains a hash of every diagnostic that has been emitted by /// this `DiagCtxt`. These hashes is used to avoid emitting the same error @@ -1004,9 +1007,9 @@ impl DiagCtxt { let mut error_codes = inner .emitted_diagnostic_codes .iter() - .filter_map(|code| { + .filter_map(|&code| { if registry.try_find_description(code).is_ok().clone() { - Some(code.clone()) + Some(code.to_string()) } else { None } @@ -1052,8 +1055,8 @@ impl DiagCtxt { /// /// Used to suppress emitting the same error multiple times with extended explanation when /// calling `-Zteach`. - pub fn must_teach(&self, code: &str) -> bool { - self.inner.borrow_mut().taught_diagnostics.insert(code.to_string()) + pub fn must_teach(&self, code: ErrCode) -> bool { + self.inner.borrow_mut().taught_diagnostics.insert(code) } pub fn force_print_diagnostic(&self, db: Diagnostic) { @@ -1313,8 +1316,8 @@ impl DiagCtxtInner { let mut guaranteed = None; (*TRACK_DIAGNOSTIC)(diagnostic, &mut |mut diagnostic| { - if let Some(ref code) = diagnostic.code { - self.emitted_diagnostic_codes.insert(code.clone()); + if let Some(code) = diagnostic.code { + self.emitted_diagnostic_codes.insert(code); } let already_emitted = { diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs index f26d8e7ebdc34..8834d04d9718b 100644 --- a/compiler/rustc_errors/src/registry.rs +++ b/compiler/rustc_errors/src/registry.rs @@ -1,3 +1,4 @@ +use crate::ErrCode; use rustc_data_structures::fx::FxHashMap; #[derive(Debug)] @@ -5,17 +6,17 @@ pub struct InvalidErrorCode; #[derive(Clone)] pub struct Registry { - long_descriptions: FxHashMap<&'static str, &'static str>, + long_descriptions: FxHashMap, } impl Registry { - pub fn new(long_descriptions: &[(&'static str, &'static str)]) -> Registry { + pub fn new(long_descriptions: &[(ErrCode, &'static str)]) -> Registry { Registry { long_descriptions: long_descriptions.iter().copied().collect() } } /// Returns `InvalidErrorCode` if the code requested does not exist in the /// registry. - pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> { - self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode) + pub fn try_find_description(&self, code: ErrCode) -> Result<&'static str, InvalidErrorCode> { + self.long_descriptions.get(&code).copied().ok_or(InvalidErrorCode) } } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 4a1c00f0104fd..2584ff62e98e6 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -1,4 +1,5 @@ use rustc_ast::ast; +use rustc_errors::codes::*; use rustc_macros::Diagnostic; use rustc_session::Limit; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent}; @@ -175,7 +176,7 @@ pub(crate) struct TakesNoArguments<'a> { } #[derive(Diagnostic)] -#[diag(expand_feature_removed, code = "E0557")] +#[diag(expand_feature_removed, code = E0557)] pub(crate) struct FeatureRemoved<'a> { #[primary_span] #[label] @@ -191,7 +192,7 @@ pub(crate) struct FeatureRemovedReason<'a> { } #[derive(Diagnostic)] -#[diag(expand_feature_not_allowed, code = "E0725")] +#[diag(expand_feature_not_allowed, code = E0725)] pub(crate) struct FeatureNotAllowed { #[primary_span] pub span: Span, @@ -210,7 +211,7 @@ pub(crate) struct RecursionLimitReached<'a> { } #[derive(Diagnostic)] -#[diag(expand_malformed_feature_attribute, code = "E0556")] +#[diag(expand_malformed_feature_attribute, code = E0556)] pub(crate) struct MalformedFeatureAttribute { #[primary_span] pub span: Span, @@ -347,7 +348,7 @@ pub(crate) struct ModuleInBlockName { } #[derive(Diagnostic)] -#[diag(expand_module_file_not_found, code = "E0583")] +#[diag(expand_module_file_not_found, code = E0583)] #[help] #[note] pub(crate) struct ModuleFileNotFound { @@ -359,7 +360,7 @@ pub(crate) struct ModuleFileNotFound { } #[derive(Diagnostic)] -#[diag(expand_module_multiple_candidates, code = "E0761")] +#[diag(expand_module_multiple_candidates, code = E0761)] #[help] pub(crate) struct ModuleMultipleCandidates { #[primary_span] diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 3aad510f3660f..c22daad334fc5 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashMap; -use rustc_errors::struct_span_code_err; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index bfe88df4e1a55..5e9076243f8be 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -7,7 +7,9 @@ use crate::fluent_generated as fluent; use crate::traits::error_reporting::report_object_safety_error; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed}; +use rustc_errors::{ + codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed, +}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::FulfillmentError; diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 4284758b1172e..30b10446afcc9 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -5,7 +5,9 @@ use crate::astconv::{ }; use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; use rustc_ast::ast::ParamKindOrd; -use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ + codes::*, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 33e782abc68ed..98cd8a085baef 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -1,5 +1,5 @@ use rustc_ast::TraitObjectSyntax; -use rustc_errors::{Diagnostic, StashKey}; +use rustc_errors::{codes::*, Diagnostic, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 7c97c2a1a6ff2..2dec0ab4355ff 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -18,8 +18,8 @@ use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ - error_code, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, FatalError, MultiSpan, + codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + FatalError, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; @@ -1072,9 +1072,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(binding) = binding && let ConvertedBindingKind::Equality(_) = binding.kind { - error_code!(E0222) + E0222 } else { - error_code!(E0221) + E0221 }, ); @@ -1630,7 +1630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let reported = tcx .dcx() .struct_span_err(span, msg) - .with_code(rustc_errors::error_code!(E0624)) + .with_code(E0624) .with_span_label(span, format!("private {kind}")) .with_span_label(def_span, format!("{kind} defined here")) .emit(); diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 5f35f75c77b0f..2d85ad5789ecc 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -2,7 +2,7 @@ use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBou use crate::bounds::Bounds; use crate::errors::TraitObjectDeclaredWithNoTraits; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_errors::struct_span_code_err; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c63bafcdcd464..2fe3499e8e690 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -5,7 +5,7 @@ use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; use super::*; use rustc_attr as attr; -use rustc_errors::{ErrorGuaranteed, MultiSpan}; +use rustc_errors::{codes::*, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 57829d9d4184a..479421af77fef 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2,7 +2,7 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; +use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; @@ -1382,7 +1382,7 @@ fn compare_number_of_generics<'tcx>( kind = kind, ), ); - err.code("E0049".into()); + err.code(E0049); let msg = format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),); diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 3275a81c3ddc7..9fe95487bb9e0 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -2,7 +2,7 @@ // // We don't do any drop checking during hir typeck. use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_code_err, ErrorGuaranteed}; +use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_middle::ty::util::CheckRegions; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 60e4403c1c70e..2d0d6611444c5 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -8,7 +8,7 @@ use crate::errors::{ }; use hir::def_id::DefId; -use rustc_errors::{struct_span_code_err, DiagnosticMessage}; +use rustc_errors::{codes::*, struct_span_code_err, DiagnosticMessage}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 70213ee0614f8..0978a5e65969a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -4,7 +4,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{ - pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, + codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, }; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 63ea02720145e..951440d6a2d0b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::struct_span_code_err; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index dafa899ef248f..8cf1f2c9407f6 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -6,7 +6,7 @@ // mappings. That mapping code resides here. use crate::errors; -use rustc_errors::{error_code, struct_span_code_err}; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; @@ -61,7 +61,7 @@ fn enforce_trait_manually_implementable( // Maintain explicit error code for `Unsize`, since it has a useful // explanation about using `CoerceUnsized` instead. if Some(trait_def_id) == tcx.lang_items().unsize_trait() { - err.code(error_code!(E0328)); + err.code(E0328); } return Err(err.emit()); diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index e4c407af53ff0..e3b5c724cdee2 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -1,7 +1,7 @@ //! Unsafety checker: every impl either implements a trait defined in this //! crate or pertains to a type defined in this crate. -use rustc_errors::struct_span_code_err; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::Unsafety; use rustc_middle::ty::TyCtxt; 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 a857e01f4fa7b..97d792e49aeaa 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -8,7 +8,7 @@ use rustc_ast::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_errors::struct_span_code_err; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f14390b77c6e2..e5871276d6414 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -2,8 +2,8 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, - Level, MultiSpan, + codes::*, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, + MultiSpan, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -52,7 +52,7 @@ pub struct AssocKindMismatchWrapInBracesSugg { } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_item_not_found, code = "E0220")] +#[diag(hir_analysis_assoc_item_not_found, code = E0220)] pub struct AssocItemNotFound<'a> { #[primary_span] pub span: Span, @@ -122,7 +122,7 @@ pub enum AssocItemNotFoundSugg<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")] +#[diag(hir_analysis_unrecognized_atomic_operation, code = E0092)] pub struct UnrecognizedAtomicOperation<'a> { #[primary_span] #[label] @@ -131,7 +131,7 @@ pub struct UnrecognizedAtomicOperation<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")] +#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = E0094)] pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[primary_span] #[label] @@ -142,7 +142,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_unrecognized_intrinsic_function, code = "E0093")] +#[diag(hir_analysis_unrecognized_intrinsic_function, code = E0093)] pub struct UnrecognizedIntrinsicFunction { #[primary_span] #[label] @@ -151,7 +151,7 @@ pub struct UnrecognizedIntrinsicFunction { } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = "E0195")] +#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = E0195)] pub struct LifetimesOrBoundsMismatchOnTrait { #[primary_span] #[label] @@ -178,7 +178,7 @@ pub struct AsyncTraitImplShouldBeAsync { } #[derive(Diagnostic)] -#[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")] +#[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] pub struct DropImplOnWrongItem { #[primary_span] #[label] @@ -186,7 +186,7 @@ pub struct DropImplOnWrongItem { } #[derive(Diagnostic)] -#[diag(hir_analysis_field_already_declared, code = "E0124")] +#[diag(hir_analysis_field_already_declared, code = E0124)] pub struct FieldAlreadyDeclared { pub field_name: Ident, #[primary_span] @@ -197,7 +197,7 @@ pub struct FieldAlreadyDeclared { } #[derive(Diagnostic)] -#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = "E0184")] +#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = E0184)] pub struct CopyImplOnTypeWithDtor { #[primary_span] #[label] @@ -205,14 +205,14 @@ pub struct CopyImplOnTypeWithDtor { } #[derive(Diagnostic)] -#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")] +#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)] pub struct MultipleRelaxedDefaultBounds { #[primary_span] pub spans: Vec, } #[derive(Diagnostic)] -#[diag(hir_analysis_copy_impl_on_non_adt, code = "E0206")] +#[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)] pub struct CopyImplOnNonAdt { #[primary_span] #[label] @@ -228,7 +228,7 @@ pub struct ConstParamTyImplOnNonAdt { } #[derive(Diagnostic)] -#[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")] +#[diag(hir_analysis_trait_object_declared_with_no_traits, code = E0224)] pub struct TraitObjectDeclaredWithNoTraits { #[primary_span] pub span: Span, @@ -237,14 +237,14 @@ pub struct TraitObjectDeclaredWithNoTraits { } #[derive(Diagnostic)] -#[diag(hir_analysis_ambiguous_lifetime_bound, code = "E0227")] +#[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)] pub struct AmbiguousLifetimeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_type_binding_not_allowed, code = "E0229")] +#[diag(hir_analysis_assoc_type_binding_not_allowed, code = E0229)] pub struct AssocTypeBindingNotAllowed { #[primary_span] #[label] @@ -264,7 +264,7 @@ pub struct ParenthesizedFnTraitExpansion { } #[derive(Diagnostic)] -#[diag(hir_analysis_typeof_reserved_keyword_used, code = "E0516")] +#[diag(hir_analysis_typeof_reserved_keyword_used, code = E0516)] pub struct TypeofReservedKeywordUsed<'tcx> { pub ty: Ty<'tcx>, #[primary_span] @@ -275,7 +275,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_value_of_associated_struct_already_specified, code = "E0719")] +#[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)] pub struct ValueOfAssociatedStructAlreadySpecified { #[primary_span] #[label] @@ -320,7 +320,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params); err.span(self.span); - err.code(error_code!(E0393)); + err.code(E0393); err.arg("parameterCount", self.missing_type_params.len()); err.arg( "parameters", @@ -373,7 +373,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams { } #[derive(Diagnostic)] -#[diag(hir_analysis_manual_implementation, code = "E0183")] +#[diag(hir_analysis_manual_implementation, code = E0183)] #[help] pub struct ManualImplementation { #[primary_span] @@ -421,7 +421,7 @@ pub struct SelfInImplSelf { } #[derive(Diagnostic)] -#[diag(hir_analysis_linkage_type, code = "E0791")] +#[diag(hir_analysis_linkage_type, code = E0791)] pub(crate) struct LinkageType { #[primary_span] pub span: Span, @@ -429,7 +429,7 @@ pub(crate) struct LinkageType { #[derive(Diagnostic)] #[help] -#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = "E0055")] +#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = E0055)] pub struct AutoDerefReachedRecursionLimit<'a> { #[primary_span] #[label] @@ -440,7 +440,7 @@ pub struct AutoDerefReachedRecursionLimit<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_where_clause_on_main, code = "E0646")] +#[diag(hir_analysis_where_clause_on_main, code = E0646)] pub(crate) struct WhereClauseOnMain { #[primary_span] pub span: Span, @@ -485,7 +485,7 @@ pub(crate) struct StartTargetFeature { } #[derive(Diagnostic)] -#[diag(hir_analysis_start_not_async, code = "E0752")] +#[diag(hir_analysis_start_not_async, code = E0752)] pub(crate) struct StartAsync { #[primary_span] #[label] @@ -493,7 +493,7 @@ pub(crate) struct StartAsync { } #[derive(Diagnostic)] -#[diag(hir_analysis_start_function_where, code = "E0647")] +#[diag(hir_analysis_start_function_where, code = E0647)] pub(crate) struct StartFunctionWhere { #[primary_span] #[label] @@ -501,7 +501,7 @@ pub(crate) struct StartFunctionWhere { } #[derive(Diagnostic)] -#[diag(hir_analysis_start_function_parameters, code = "E0132")] +#[diag(hir_analysis_start_function_parameters, code = E0132)] pub(crate) struct StartFunctionParameters { #[primary_span] #[label] @@ -509,14 +509,14 @@ pub(crate) struct StartFunctionParameters { } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_return_type_generic, code = "E0131")] +#[diag(hir_analysis_main_function_return_type_generic, code = E0131)] pub(crate) struct MainFunctionReturnTypeGeneric { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_async, code = "E0752")] +#[diag(hir_analysis_main_function_async, code = E0752)] pub(crate) struct MainFunctionAsync { #[primary_span] pub span: Span, @@ -525,7 +525,7 @@ pub(crate) struct MainFunctionAsync { } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_generic_parameters, code = "E0131")] +#[diag(hir_analysis_main_function_generic_parameters, code = E0131)] pub(crate) struct MainFunctionGenericParameters { #[primary_span] pub span: Span, @@ -534,7 +534,7 @@ pub(crate) struct MainFunctionGenericParameters { } #[derive(Diagnostic)] -#[diag(hir_analysis_variadic_function_compatible_convention, code = "E0045")] +#[diag(hir_analysis_variadic_function_compatible_convention, code = E0045)] pub(crate) struct VariadicFunctionCompatibleConvention<'a> { #[primary_span] #[label] @@ -587,7 +587,7 @@ pub(crate) struct TypeOf<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_pass_to_variadic_function, code = "E0617")] +#[diag(hir_analysis_pass_to_variadic_function, code = E0617)] pub(crate) struct PassToVariadicFunction<'tcx, 'a> { #[primary_span] pub span: Span, @@ -601,7 +601,7 @@ pub(crate) struct PassToVariadicFunction<'tcx, 'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_cast_thin_pointer_to_fat_pointer, code = "E0607")] +#[diag(hir_analysis_cast_thin_pointer_to_fat_pointer, code = E0607)] pub(crate) struct CastThinPointerToFatPointer<'tcx> { #[primary_span] pub span: Span, @@ -610,7 +610,7 @@ pub(crate) struct CastThinPointerToFatPointer<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_union_field, code = "E0740")] +#[diag(hir_analysis_invalid_union_field, code = E0740)] pub(crate) struct InvalidUnionField { #[primary_span] pub field_span: Span, @@ -649,7 +649,7 @@ pub(crate) struct ReturnTypeNotationEqualityBound { } #[derive(Diagnostic)] -#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")] +#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = E0121)] pub(crate) struct PlaceholderNotAllowedItemSignatures { #[primary_span] #[label] @@ -658,7 +658,7 @@ pub(crate) struct PlaceholderNotAllowedItemSignatures { } #[derive(Diagnostic)] -#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = "E0212")] +#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)] pub(crate) struct AssociatedTypeTraitUninferredGenericParams { #[primary_span] pub span: Span, @@ -684,7 +684,7 @@ pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion } #[derive(Diagnostic)] -#[diag(hir_analysis_enum_discriminant_overflowed, code = "E0370")] +#[diag(hir_analysis_enum_discriminant_overflowed, code = E0370)] #[note] pub(crate) struct EnumDiscriminantOverflowed { #[primary_span] @@ -774,7 +774,7 @@ pub(crate) struct SIMDFFIHighlyExperimental { #[derive(Diagnostic)] pub enum ImplNotMarkedDefault { - #[diag(hir_analysis_impl_not_marked_default, code = "E0520")] + #[diag(hir_analysis_impl_not_marked_default, code = E0520)] #[note] Ok { #[primary_span] @@ -784,7 +784,7 @@ pub enum ImplNotMarkedDefault { ok_label: Span, ident: Symbol, }, - #[diag(hir_analysis_impl_not_marked_default_err, code = "E0520")] + #[diag(hir_analysis_impl_not_marked_default_err, code = E0520)] #[note] Err { #[primary_span] @@ -795,7 +795,7 @@ pub enum ImplNotMarkedDefault { } #[derive(Diagnostic)] -#[diag(hir_analysis_missing_trait_item, code = "E0046")] +#[diag(hir_analysis_missing_trait_item, code = E0046)] pub(crate) struct MissingTraitItem { #[primary_span] #[label] @@ -846,7 +846,7 @@ pub(crate) struct MissingTraitItemSuggestionNone { } #[derive(Diagnostic)] -#[diag(hir_analysis_missing_one_of_trait_item, code = "E0046")] +#[diag(hir_analysis_missing_one_of_trait_item, code = E0046)] pub(crate) struct MissingOneOfTraitItem { #[primary_span] #[label] @@ -857,7 +857,7 @@ pub(crate) struct MissingOneOfTraitItem { } #[derive(Diagnostic)] -#[diag(hir_analysis_missing_trait_item_unstable, code = "E0046")] +#[diag(hir_analysis_missing_trait_item_unstable, code = E0046)] #[note] pub(crate) struct MissingTraitItemUnstable { #[primary_span] @@ -872,7 +872,7 @@ pub(crate) struct MissingTraitItemUnstable { } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_enum_variant, code = "E0731")] +#[diag(hir_analysis_transparent_enum_variant, code = E0731)] pub(crate) struct TransparentEnumVariant { #[primary_span] #[label] @@ -886,7 +886,7 @@ pub(crate) struct TransparentEnumVariant { } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_non_zero_sized_enum, code = "E0690")] +#[diag(hir_analysis_transparent_non_zero_sized_enum, code = E0690)] pub(crate) struct TransparentNonZeroSizedEnum<'a> { #[primary_span] #[label] @@ -898,7 +898,7 @@ pub(crate) struct TransparentNonZeroSizedEnum<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_non_zero_sized, code = "E0690")] +#[diag(hir_analysis_transparent_non_zero_sized, code = E0690)] pub(crate) struct TransparentNonZeroSized<'a> { #[primary_span] #[label] @@ -1045,7 +1045,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside, code = "E0390")] +#[diag(hir_analysis_inherent_ty_outside, code = E0390)] #[help] pub struct InherentTyOutside { #[primary_span] @@ -1054,7 +1054,7 @@ pub struct InherentTyOutside { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +#[diag(hir_analysis_coerce_unsized_may, code = E0378)] pub struct DispatchFromDynCoercion<'a> { #[primary_span] pub span: Span, @@ -1066,14 +1066,14 @@ pub struct DispatchFromDynCoercion<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_dispatch_from_dyn_repr, code = "E0378")] +#[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)] pub struct DispatchFromDynRepr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_relevant, code = "E0390")] +#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)] #[help] pub struct InherentTyOutsideRelevant { #[primary_span] @@ -1083,7 +1083,7 @@ pub struct InherentTyOutsideRelevant { } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_new, code = "E0116")] +#[diag(hir_analysis_inherent_ty_outside_new, code = E0116)] #[note] pub struct InherentTyOutsideNew { #[primary_span] @@ -1092,7 +1092,7 @@ pub struct InherentTyOutsideNew { } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_primitive, code = "E0390")] +#[diag(hir_analysis_inherent_ty_outside_primitive, code = E0390)] #[help] pub struct InherentTyOutsidePrimitive { #[primary_span] @@ -1102,7 +1102,7 @@ pub struct InherentTyOutsidePrimitive { } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_primitive_ty, code = "E0390")] +#[diag(hir_analysis_inherent_primitive_ty, code = E0390)] #[help] pub struct InherentPrimitiveTy<'a> { #[primary_span] @@ -1118,7 +1118,7 @@ pub struct InherentPrimitiveTyNote<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_dyn, code = "E0785")] +#[diag(hir_analysis_inherent_dyn, code = E0785)] #[note] pub struct InherentDyn { #[primary_span] @@ -1127,7 +1127,7 @@ pub struct InherentDyn { } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_nominal, code = "E0118")] +#[diag(hir_analysis_inherent_nominal, code = E0118)] #[note] pub struct InherentNominal { #[primary_span] @@ -1136,7 +1136,7 @@ pub struct InherentNominal { } #[derive(Diagnostic)] -#[diag(hir_analysis_dispatch_from_dyn_zst, code = "E0378")] +#[diag(hir_analysis_dispatch_from_dyn_zst, code = E0378)] #[note] pub struct DispatchFromDynZST<'a> { #[primary_span] @@ -1146,7 +1146,7 @@ pub struct DispatchFromDynZST<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +#[diag(hir_analysis_coerce_unsized_may, code = E0378)] pub struct DispatchFromDynSingle<'a> { #[primary_span] pub span: Span, @@ -1156,7 +1156,7 @@ pub struct DispatchFromDynSingle<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_dispatch_from_dyn_multi, code = "E0378")] +#[diag(hir_analysis_dispatch_from_dyn_multi, code = E0378)] #[note] pub struct DispatchFromDynMulti { #[primary_span] @@ -1168,7 +1168,7 @@ pub struct DispatchFromDynMulti { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = "E0376")] +#[diag(hir_analysis_coerce_unsized_may, code = E0376)] pub struct DispatchFromDynStruct<'a> { #[primary_span] pub span: Span, @@ -1176,7 +1176,7 @@ pub struct DispatchFromDynStruct<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = "E0377")] +#[diag(hir_analysis_coerce_unsized_may, code = E0377)] pub struct DispatchFromDynSame<'a> { #[primary_span] pub span: Span, @@ -1188,7 +1188,7 @@ pub struct DispatchFromDynSame<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = "E0374")] +#[diag(hir_analysis_coerce_unsized_may, code = E0374)] pub struct CoerceUnsizedOneField<'a> { #[primary_span] pub span: Span, @@ -1198,7 +1198,7 @@ pub struct CoerceUnsizedOneField<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_multi, code = "E0375")] +#[diag(hir_analysis_coerce_unsized_multi, code = E0375)] #[note] pub struct CoerceUnsizedMulti { #[primary_span] @@ -1211,7 +1211,7 @@ pub struct CoerceUnsizedMulti { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +#[diag(hir_analysis_coerce_unsized_may, code = E0378)] pub struct CoerceUnsizedMay<'a> { #[primary_span] pub span: Span, @@ -1219,7 +1219,7 @@ pub struct CoerceUnsizedMay<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_trait_cannot_impl_for_ty, code = "E0204")] +#[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)] pub struct TraitCannotImplForTy { #[primary_span] pub span: Span, @@ -1241,7 +1241,7 @@ pub struct ImplForTyRequires { } #[derive(Diagnostic)] -#[diag(hir_analysis_traits_with_defualt_impl, code = "E0321")] +#[diag(hir_analysis_traits_with_defualt_impl, code = E0321)] #[note] pub struct TraitsWithDefaultImpl<'a> { #[primary_span] @@ -1252,7 +1252,7 @@ pub struct TraitsWithDefaultImpl<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_cross_crate_traits, code = "E0321")] +#[diag(hir_analysis_cross_crate_traits, code = E0321)] pub struct CrossCrateTraits<'a> { #[primary_span] #[label] @@ -1262,7 +1262,7 @@ pub struct CrossCrateTraits<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_cross_crate_traits_defined, code = "E0321")] +#[diag(hir_analysis_cross_crate_traits_defined, code = E0321)] pub struct CrossCrateTraitsDefined { #[primary_span] #[label] @@ -1271,7 +1271,7 @@ pub struct CrossCrateTraitsDefined { } #[derive(Diagnostic)] -#[diag(hir_analysis_ty_param_first_local, code = "E0210")] +#[diag(hir_analysis_ty_param_first_local, code = E0210)] #[note] pub struct TyParamFirstLocal<'a> { #[primary_span] @@ -1284,7 +1284,7 @@ pub struct TyParamFirstLocal<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_ty_param_some, code = "E0210")] +#[diag(hir_analysis_ty_param_some, code = E0210)] #[note] pub struct TyParamSome<'a> { #[primary_span] @@ -1297,7 +1297,7 @@ pub struct TyParamSome<'a> { #[derive(Diagnostic)] pub enum OnlyCurrentTraits<'a> { - #[diag(hir_analysis_only_current_traits_outside, code = "E0117")] + #[diag(hir_analysis_only_current_traits_outside, code = E0117)] Outside { #[primary_span] #[label(hir_analysis_only_current_traits_label)] @@ -1317,7 +1317,7 @@ pub enum OnlyCurrentTraits<'a> { #[subdiagnostic] sugg: Option>, }, - #[diag(hir_analysis_only_current_traits_primitive, code = "E0117")] + #[diag(hir_analysis_only_current_traits_primitive, code = E0117)] Primitive { #[primary_span] #[label(hir_analysis_only_current_traits_label)] @@ -1337,7 +1337,7 @@ pub enum OnlyCurrentTraits<'a> { #[subdiagnostic] sugg: Option>, }, - #[diag(hir_analysis_only_current_traits_arbitrary, code = "E0117")] + #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)] Arbitrary { #[primary_span] #[label(hir_analysis_only_current_traits_label)] @@ -1412,7 +1412,7 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_static_mut_ref, code = "E0796")] +#[diag(hir_analysis_static_mut_ref, code = E0796)] #[note] pub struct StaticMutRef { #[primary_span] diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 2fe08ead72b2a..c072891e2952e 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -12,7 +12,7 @@ use crate::constrained_generic_params as cgp; use min_specialization::check_min_specialization; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::struct_span_code_err; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_middle::query::Providers; diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs index b061d6371388f..6846e4defe5e5 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors.rs @@ -6,18 +6,18 @@ pub use self::{ missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*, }; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::{DiagnosticBuilder, ErrCode}; use rustc_session::Session; pub trait StructuredDiagnostic<'tcx> { fn session(&self) -> &Session; - fn code(&self) -> String; + fn code(&self) -> ErrCode; fn diagnostic(&self) -> DiagnosticBuilder<'tcx> { let err = self.diagnostic_common(); - if self.session().teach(&self.code()) { + if self.session().teach(self.code()) { self.diagnostic_extended(err) } else { self.diagnostic_regular(err) diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs index 6f4435db41143..50b4ef623ac7e 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs @@ -1,5 +1,5 @@ use crate::{errors, structured_errors::StructuredDiagnostic}; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode}; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -16,8 +16,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> { self.sess } - fn code(&self) -> String { - rustc_errors::error_code!(E0617) + fn code(&self) -> ErrCode { + E0617 } fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs index 19cac4a38aaab..54d54a2af93a6 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs @@ -1,5 +1,5 @@ use crate::{errors, structured_errors::StructuredDiagnostic}; -use rustc_errors::DiagnosticBuilder; +use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode}; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -16,8 +16,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { self.sess } - fn code(&self) -> String { - rustc_errors::error_code!(E0607) + fn code(&self) -> ErrCode { + E0607 } fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index ba81e7f1f8165..501915d2e7e53 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -1,5 +1,7 @@ use crate::structured_errors::StructuredDiagnostic; -use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; +use rustc_errors::{ + codes::*, pluralize, Applicability, Diagnostic, DiagnosticBuilder, ErrCode, MultiSpan, +}; use rustc_hir as hir; use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; use rustc_session::Session; @@ -1105,8 +1107,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> { self.tcx.sess } - fn code(&self) -> String { - rustc_errors::error_code!(E0107) + fn code(&self) -> ErrCode { + E0107 } fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index bd8a2024caa1e..a0ac839f3dd2c 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -33,7 +33,7 @@ use super::FnCtxt; use crate::errors; use crate::type_error_struct; use hir::ExprKind; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{codes::*, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::mir::Mutability; diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 858faf161f6e8..ca636ebcade04 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -36,7 +36,9 @@ //! ``` use crate::FnCtxt; -use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; +use rustc_errors::{ + codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 4f92906888796..b75cf4b4e8bca 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -3,8 +3,8 @@ use std::borrow::Cow; use crate::fluent_generated as fluent; use rustc_errors::{ - AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, MultiSpan, - SubdiagnosticMessage, + codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, + MultiSpan, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -15,7 +15,7 @@ use rustc_span::{ }; #[derive(Diagnostic)] -#[diag(hir_typeck_field_multiply_specified_in_initializer, code = "E0062")] +#[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)] pub struct FieldMultiplySpecifiedInInitializer { #[primary_span] #[label] @@ -26,7 +26,7 @@ pub struct FieldMultiplySpecifiedInInitializer { } #[derive(Diagnostic)] -#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = "E0572")] +#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = E0572)] pub struct ReturnStmtOutsideOfFnBody { #[primary_span] pub span: Span, @@ -62,14 +62,14 @@ pub struct RustCallIncorrectArgs { } #[derive(Diagnostic)] -#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = "E0627")] +#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = E0627)] pub struct YieldExprOutsideOfCoroutine { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_struct_expr_non_exhaustive, code = "E0639")] +#[diag(hir_typeck_struct_expr_non_exhaustive, code = E0639)] pub struct StructExprNonExhaustive { #[primary_span] pub span: Span, @@ -77,7 +77,7 @@ pub struct StructExprNonExhaustive { } #[derive(Diagnostic)] -#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = "E0699")] +#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = E0699)] pub struct MethodCallOnUnknownRawPointee { #[primary_span] pub span: Span, @@ -92,14 +92,14 @@ pub struct MissingFnLangItems { } #[derive(Diagnostic)] -#[diag(hir_typeck_functional_record_update_on_non_struct, code = "E0436")] +#[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)] pub struct FunctionalRecordUpdateOnNonStruct { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_address_of_temporary_taken, code = "E0745")] +#[diag(hir_typeck_address_of_temporary_taken, code = E0745)] pub struct AddressOfTemporaryTaken { #[primary_span] #[label] @@ -145,7 +145,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_explicit_destructor, code = "E0040")] +#[diag(hir_typeck_explicit_destructor, code = E0040)] pub struct ExplicitDestructorCall { #[primary_span] #[label] @@ -168,7 +168,7 @@ pub enum ExplicitDestructorCallSugg { } #[derive(Diagnostic)] -#[diag(hir_typeck_missing_parentheses_in_range, code = "E0689")] +#[diag(hir_typeck_missing_parentheses_in_range, code = E0689)] pub struct MissingParenthesesInRange { #[primary_span] #[label(hir_typeck_missing_parentheses_in_range)] @@ -321,7 +321,7 @@ impl HelpUseLatestEdition { } #[derive(Diagnostic)] -#[diag(hir_typeck_invalid_callee, code = "E0618")] +#[diag(hir_typeck_invalid_callee, code = E0618)] pub struct InvalidCallee { #[primary_span] pub span: Span, @@ -329,7 +329,7 @@ pub struct InvalidCallee { } #[derive(Diagnostic)] -#[diag(hir_typeck_int_to_fat, code = "E0606")] +#[diag(hir_typeck_int_to_fat, code = E0606)] pub struct IntToWide<'tcx> { #[primary_span] #[label(hir_typeck_int_to_fat_label)] @@ -510,7 +510,7 @@ pub struct TrivialCast<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_no_associated_item, code = "E0599")] +#[diag(hir_typeck_no_associated_item, code = E0599)] pub struct NoAssociatedItem { #[primary_span] pub span: Span, @@ -532,7 +532,7 @@ pub struct CandidateTraitNote { } #[derive(Diagnostic)] -#[diag(hir_typeck_cannot_cast_to_bool, code = "E0054")] +#[diag(hir_typeck_cannot_cast_to_bool, code = E0054)] pub struct CannotCastToBool<'tcx> { #[primary_span] pub span: Span, @@ -549,7 +549,7 @@ pub struct CastEnumDrop<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_cast_unknown_pointer, code = "E0641")] +#[diag(hir_typeck_cast_unknown_pointer, code = E0641)] pub struct CastUnknownPointer { #[primary_span] pub span: Span, @@ -600,7 +600,7 @@ pub enum CannotCastToBoolHelp { } #[derive(Diagnostic)] -#[diag(hir_typeck_ctor_is_private, code = "E0603")] +#[diag(hir_typeck_ctor_is_private, code = E0603)] pub struct CtorIsPrivate { #[primary_span] pub span: Span, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 3bc259c17b774..fafed5be8c5f5 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -25,8 +25,8 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, StashKey, + codes::*, pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, + DiagnosticBuilder, ErrCode, ErrorGuaranteed, StashKey, }; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -527,7 +527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_error(tcx, e) } Res::Def(DefKind::Variant, _) => { - let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value"); + let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, E0533, "value"); Ty::new_error(tcx, e) } _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, @@ -939,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn check_lhs_assignable( &self, lhs: &'tcx hir::Expr<'tcx>, - err_code: &'static str, + code: ErrCode, op_span: Span, adjust_err: impl FnOnce(&mut Diagnostic), ) { @@ -948,7 +948,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment"); - err.code(err_code.into()); + err.code(code); err.span_label(lhs.span, "cannot assign to this expression"); self.comes_from_while_condition(lhs.hir_id, |expr| { @@ -1244,7 +1244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diag.emit(); } - self.check_lhs_assignable(lhs, "E0070", span, |err| { + self.check_lhs_assignable(lhs, E0070, span, |err| { if let Some(rhs_ty) = self.typeck_results.borrow().expr_ty_opt(rhs) { suggest_deref_binop(err, rhs_ty); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 6a77450f075bf..2494feee1ff1d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -12,7 +12,9 @@ use crate::{ use itertools::Itertools; use rustc_ast as ast; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{pluralize, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey}; +use rustc_errors::{ + codes::*, pluralize, Applicability, Diagnostic, ErrCode, ErrorGuaranteed, MultiSpan, StashKey, +}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -177,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); } - let mut err_code = "E0061"; + let mut err_code = E0061; // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments { @@ -187,7 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Tuple(arg_types) => { // Argument length differs if arg_types.len() != provided_args.len() { - err_code = "E0057"; + err_code = E0057; } let expected_input_tys = match expected_input_tys { Some(expected_input_tys) => match expected_input_tys.get(0) { @@ -358,7 +360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if c_variadic && provided_arg_count < minimum_input_count { - err_code = "E0060"; + err_code = E0060; } for arg in provided_args.iter().skip(minimum_input_count) { @@ -443,7 +445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { formal_and_expected_inputs: IndexVec, Ty<'tcx>)>, provided_args: IndexVec>, c_variadic: bool, - err_code: &str, + err_code: ErrCode, fn_def_id: Option, call_span: Span, call_expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index e087733130e33..2dee5093e876d 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -1,5 +1,5 @@ use hir::HirId; -use rustc_errors::struct_span_code_err; +use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_index::Idx; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 36cd658314763..36aa949668ff3 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -51,7 +51,7 @@ use crate::expectation::Expectation; use crate::fn_ctxt::LoweredTy; use crate::gather_locals::GatherLocalsVisitor; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{struct_span_code_err, ErrorGuaranteed}; +use rustc_errors::{codes::*, struct_span_code_err, ErrCode, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -71,7 +71,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } #[macro_export] macro_rules! type_error_struct { - ($dcx:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({ + ($dcx:expr, $span:expr, $typ:expr, $code:expr, $($message:tt)*) => ({ let mut err = rustc_errors::struct_span_code_err!($dcx, $span, $code, $($message)*); if $typ.references_error() { @@ -375,7 +375,7 @@ fn report_unexpected_variant_res( res: Res, qpath: &hir::QPath<'_>, span: Span, - err_code: &str, + err_code: ErrCode, expected: &str, ) -> ErrorGuaranteed { let res_descr = match res { @@ -386,9 +386,9 @@ fn report_unexpected_variant_res( let err = tcx .dcx() .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`")) - .with_code(err_code.into()); + .with_code(err_code); match res { - Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => { + Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => { let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html"; err.with_span_label(span, "`fn` calls are not allowed in patterns") .with_help(format!("for more information, visit {patterns_url}")) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 47f6e3f934eca..314d28e6e044e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3,17 +3,16 @@ // ignore-tidy-filelength -use crate::errors; -use crate::errors::{CandidateTraitNote, NoAssociatedItem}; +use crate::errors::{self, CandidateTraitNote, NoAssociatedItem}; use crate::Expectation; use crate::FnCtxt; use rustc_ast::ast::Mutability; use rustc_attr::parse_confusables; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::StashKey; use rustc_errors::{ - pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan, + codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, + MultiSpan, StashKey, }; use rustc_hir as hir; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index ff82e2d653cf4..bbe6d9e967044 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -5,7 +5,7 @@ use super::{has_expected_num_generic_args, FnCtxt}; use crate::Expectation; use rustc_ast as ast; use rustc_data_structures::packed::Pu128; -use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder}; use rustc_hir as hir; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::ObligationCauseCode; @@ -44,7 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_ty }; - self.check_lhs_assignable(lhs, "E0067", op.span, |err| { + self.check_lhs_assignable(lhs, E0067, op.span, |err| { if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { if self .lookup_op_method( diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index e31eeab4c4a47..a611d0eda8574 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -3,8 +3,8 @@ use crate::{errors, FnCtxt, LoweredTy}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ - pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, - MultiSpan, + codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -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.get_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.get_code().unwrap()) { err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ); } return Err(err.emit()); @@ -907,7 +907,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => { let expected = "unit struct, unit variant or constant"; - let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected); + let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0533, expected); return Ty::new_error(tcx, e); } Res::SelfCtor(..) @@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let report_unexpected_res = |res: Res| { let expected = "tuple struct or tuple variant"; - let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0164", expected); + let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0164, expected); on_error(e); e }; @@ -1669,7 +1669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if tcx.sess.teach(&err.get_code().unwrap()) { + if tcx.sess.teach(err.get_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/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index aee99063e0396..4e9f573091b09 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1,7 +1,7 @@ use hir::GenericParamKind; use rustc_errors::{ - AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, - IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage, + codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, + DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage, }; use rustc_hir as hir; use rustc_hir::FnRetTy; @@ -33,7 +33,7 @@ pub struct OpaqueHiddenTypeDiag { } #[derive(Diagnostic)] -#[diag(infer_type_annotations_needed, code = "E0282")] +#[diag(infer_type_annotations_needed, code = E0282)] pub struct AnnotationRequired<'a> { #[primary_span] pub span: Span, @@ -51,7 +51,7 @@ pub struct AnnotationRequired<'a> { // Copy of `AnnotationRequired` for E0283 #[derive(Diagnostic)] -#[diag(infer_type_annotations_needed, code = "E0283")] +#[diag(infer_type_annotations_needed, code = E0283)] pub struct AmbiguousImpl<'a> { #[primary_span] pub span: Span, @@ -69,7 +69,7 @@ pub struct AmbiguousImpl<'a> { // Copy of `AnnotationRequired` for E0284 #[derive(Diagnostic)] -#[diag(infer_type_annotations_needed, code = "E0284")] +#[diag(infer_type_annotations_needed, code = E0284)] pub struct AmbiguousReturn<'a> { #[primary_span] pub span: Span, @@ -421,7 +421,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { } #[derive(Diagnostic)] -#[diag(infer_lifetime_mismatch, code = "E0623")] +#[diag(infer_lifetime_mismatch, code = E0623)] pub struct LifetimeMismatch<'a> { #[primary_span] pub span: Span, @@ -495,7 +495,7 @@ pub struct MismatchedStaticLifetime<'a> { #[derive(Diagnostic)] pub enum ExplicitLifetimeRequired<'a> { - #[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")] + #[diag(infer_explicit_lifetime_required_with_ident, code = E0621)] WithIdent { #[primary_span] #[label] @@ -511,7 +511,7 @@ pub enum ExplicitLifetimeRequired<'a> { #[skip_arg] new_ty: Ty<'a>, }, - #[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")] + #[diag(infer_explicit_lifetime_required_with_param_type, code = E0621)] WithParamType { #[primary_span] #[label] @@ -819,7 +819,7 @@ impl AddToDiagnostic for DynTraitConstraintSuggestion { } #[derive(Diagnostic)] -#[diag(infer_but_calling_introduces, code = "E0772")] +#[diag(infer_but_calling_introduces, code = E0772)] pub struct ButCallingIntroduces { #[label(infer_label1)] pub param_ty_span: Span, @@ -871,14 +871,14 @@ impl AddToDiagnostic for MoreTargeted { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.code(rustc_errors::error_code!(E0772)); + diag.code(E0772); diag.primary_message(fluent::infer_more_targeted); diag.arg("ident", self.ident); } } #[derive(Diagnostic)] -#[diag(infer_but_needs_to_satisfy, code = "E0759")] +#[diag(infer_but_needs_to_satisfy, code = E0759)] pub struct ButNeedsToSatisfy { #[primary_span] pub sp: Span, @@ -904,7 +904,7 @@ pub struct ButNeedsToSatisfy { } #[derive(Diagnostic)] -#[diag(infer_outlives_content, code = "E0312")] +#[diag(infer_outlives_content, code = E0312)] pub struct OutlivesContent<'a> { #[primary_span] pub span: Span, @@ -913,7 +913,7 @@ pub struct OutlivesContent<'a> { } #[derive(Diagnostic)] -#[diag(infer_outlives_bound, code = "E0476")] +#[diag(infer_outlives_bound, code = E0476)] pub struct OutlivesBound<'a> { #[primary_span] pub span: Span, @@ -922,7 +922,7 @@ pub struct OutlivesBound<'a> { } #[derive(Diagnostic)] -#[diag(infer_fulfill_req_lifetime, code = "E0477")] +#[diag(infer_fulfill_req_lifetime, code = E0477)] pub struct FulfillReqLifetime<'a> { #[primary_span] pub span: Span, @@ -932,7 +932,7 @@ pub struct FulfillReqLifetime<'a> { } #[derive(Diagnostic)] -#[diag(infer_lf_bound_not_satisfied, code = "E0478")] +#[diag(infer_lf_bound_not_satisfied, code = E0478)] pub struct LfBoundNotSatisfied<'a> { #[primary_span] pub span: Span, @@ -941,7 +941,7 @@ pub struct LfBoundNotSatisfied<'a> { } #[derive(Diagnostic)] -#[diag(infer_ref_longer_than_data, code = "E0491")] +#[diag(infer_ref_longer_than_data, code = E0491)] pub struct RefLongerThanData<'a> { #[primary_span] pub span: Span, @@ -1117,7 +1117,7 @@ pub enum PlaceholderRelationLfNotSatisfied { } #[derive(Diagnostic)] -#[diag(infer_opaque_captures_lifetime, code = "E0700")] +#[diag(infer_opaque_captures_lifetime, code = E0700)] pub struct OpaqueCapturesLifetime<'tcx> { #[primary_span] pub span: Span, @@ -1378,73 +1378,73 @@ pub enum TypeErrorAdditionalDiags { #[derive(Diagnostic)] pub enum ObligationCauseFailureCode { - #[diag(infer_oc_method_compat, code = "E0308")] + #[diag(infer_oc_method_compat, code = E0308)] MethodCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_type_compat, code = "E0308")] + #[diag(infer_oc_type_compat, code = E0308)] TypeCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_const_compat, code = "E0308")] + #[diag(infer_oc_const_compat, code = E0308)] ConstCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_try_compat, code = "E0308")] + #[diag(infer_oc_try_compat, code = E0308)] TryCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_match_compat, code = "E0308")] + #[diag(infer_oc_match_compat, code = E0308)] MatchCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_if_else_different, code = "E0308")] + #[diag(infer_oc_if_else_different, code = E0308)] IfElseDifferent { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_no_else, code = "E0317")] + #[diag(infer_oc_no_else, code = E0317)] NoElse { #[primary_span] span: Span, }, - #[diag(infer_oc_no_diverge, code = "E0308")] + #[diag(infer_oc_no_diverge, code = E0308)] NoDiverge { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_fn_main_correct_type, code = "E0580")] + #[diag(infer_oc_fn_main_correct_type, code = E0580)] FnMainCorrectType { #[primary_span] span: Span, }, - #[diag(infer_oc_fn_start_correct_type, code = "E0308")] + #[diag(infer_oc_fn_start_correct_type, code = E0308)] FnStartCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_fn_lang_correct_type, code = "E0308")] + #[diag(infer_oc_fn_lang_correct_type, code = E0308)] FnLangCorrectType { #[primary_span] span: Span, @@ -1452,33 +1452,33 @@ pub enum ObligationCauseFailureCode { subdiags: Vec, lang_item_name: Symbol, }, - #[diag(infer_oc_intrinsic_correct_type, code = "E0308")] + #[diag(infer_oc_intrinsic_correct_type, code = E0308)] IntrinsicCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_method_correct_type, code = "E0308")] + #[diag(infer_oc_method_correct_type, code = E0308)] MethodCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_closure_selfref, code = "E0644")] + #[diag(infer_oc_closure_selfref, code = E0644)] ClosureSelfref { #[primary_span] span: Span, }, - #[diag(infer_oc_cant_coerce, code = "E0308")] + #[diag(infer_oc_cant_coerce, code = E0308)] CantCoerce { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(infer_oc_generic, code = "E0308")] + #[diag(infer_oc_generic, code = E0308)] Generic { #[primary_span] span: Span, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 7882e761a0c31..e19177fccefd8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -60,7 +60,7 @@ use crate::traits::{ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{ - error_code, pluralize, struct_span_code_err, Applicability, DiagCtxt, Diagnostic, + codes::*, pluralize, struct_span_code_err, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticStyledString, ErrorGuaranteed, IntoDiagnosticArg, }; use rustc_hir as hir; @@ -2362,9 +2362,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .dcx() .struct_span_err(span, format!("{labeled_user_string} may not live long enough")); err.code(match sub.kind() { - ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309), - ty::ReStatic => error_code!(E0310), - _ => error_code!(E0311), + ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => E0309, + ty::ReStatic => E0310, + _ => E0311, }); '_explain: { diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 03c8e08aa01ac..cf1e042c529a4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -5,7 +5,7 @@ use crate::errors::{ use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; -use rustc_errors::{DiagnosticBuilder, IntoDiagnosticArg}; +use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode, IntoDiagnosticArg}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def::{CtorOf, DefKind, Namespace}; @@ -43,12 +43,12 @@ pub enum TypeAnnotationNeeded { E0284, } -impl Into for TypeAnnotationNeeded { - fn into(self) -> String { +impl Into for TypeAnnotationNeeded { + fn into(self) -> ErrCode { match self { - Self::E0282 => rustc_errors::error_code!(E0282), - Self::E0283 => rustc_errors::error_code!(E0283), - Self::E0284 => rustc_errors::error_code!(E0284), + Self::E0282 => E0282, + Self::E0283 => E0283, + Self::E0284 => E0284, } } } 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 21ea48c6c83da..0e7c641e0e0b8 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.get_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.get_code().unwrap()) { diag.help( "given an associated type `T` and a method `foo`: ``` diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 6f218019dee5a..eabc1b953af1c 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -2,7 +2,7 @@ use super::ObjectSafetyViolation; use crate::infer::InferCtxt; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Map; diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 841d282a09942..3bd0c1b803199 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,11 +1,11 @@ use crate::fluent_generated as fluent; -use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage}; +use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessage}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(lint_overruled_attribute, code = "E0453")] +#[diag(lint_overruled_attribute, code = E0453)] pub struct OverruledAttribute<'a> { #[primary_span] pub span: Span, @@ -48,7 +48,7 @@ impl AddToDiagnostic for OverruledAttributeSub { } #[derive(Diagnostic)] -#[diag(lint_malformed_attribute, code = "E0452")] +#[diag(lint_malformed_attribute, code = E0452)] pub struct MalformedAttribute { #[primary_span] pub span: Span, @@ -67,7 +67,7 @@ pub enum MalformedAttributeSub { } #[derive(Diagnostic)] -#[diag(lint_unknown_tool_in_scoped_lint, code = "E0710")] +#[diag(lint_unknown_tool_in_scoped_lint, code = E0710)] pub struct UnknownToolInScopedLint { #[primary_span] pub span: Option, @@ -78,7 +78,7 @@ pub struct UnknownToolInScopedLint { } #[derive(Diagnostic)] -#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = "E0783")] +#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = E0783)] pub struct BuiltinEllipsisInclusiveRangePatterns { #[primary_span] pub span: Span, @@ -95,13 +95,13 @@ pub struct RequestedLevel<'a> { } #[derive(Diagnostic)] -#[diag(lint_unsupported_group, code = "E0602")] +#[diag(lint_unsupported_group, code = E0602)] pub struct UnsupportedGroup { pub lint_group: String, } #[derive(Diagnostic)] -#[diag(lint_check_name_unknown_tool, code = "E0602")] +#[diag(lint_check_name_unknown_tool, code = E0602)] pub struct CheckNameUnknownTool<'a> { pub tool_name: Symbol, #[subdiagnostic] diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index e19bb1cb62f5a..f916deb4a46d1 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,8 +5,8 @@ use std::num::NonZeroU32; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ - AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, DiagnosticMessage, - DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle, + codes::*, AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, + DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -1065,7 +1065,7 @@ pub enum UnknownLintSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_unknown_lint, code = "E0602")] +#[diag(lint_unknown_lint, code = E0602)] pub struct UnknownLintFromCommandLine<'a> { pub name: String, #[subdiagnostic] diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 0b7ecff8148b3..85bb9584a0575 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -209,9 +209,9 @@ impl DiagnosticDeriveVariantBuilder { if path.is_ident("code") { self.code.set_once((), path.span().unwrap()); - let code = nested.parse::()?; + let code = nested.parse::()?; tokens.extend(quote! { - diag.code(#code.to_string()); + diag.code(#code); }); } else { span_err(path.span().unwrap(), "unknown argument") diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 135b9e32fe7e6..33dffe6998a1e 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -20,7 +20,7 @@ use synstructure::Structure; /// # extern crate rust_middle; /// # use rustc_middle::ty::Ty; /// #[derive(Diagnostic)] -/// #[diag(borrowck_move_out_of_borrow, code = "E0505")] +/// #[diag(borrowck_move_out_of_borrow, code = E0505)] /// pub struct MoveOutOfBorrowError<'tcx> { /// pub name: Ident, /// pub ty: Ty<'tcx>, diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 27c26d3178144..d17bf0cf708f6 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -4,7 +4,7 @@ use std::{ }; use rustc_errors::{ - error_code, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, + codes::*, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_macros::Diagnostic; use rustc_session::config; @@ -122,7 +122,7 @@ pub struct WasmImportForm { } #[derive(Diagnostic)] -#[diag(metadata_empty_link_name, code = "E0454")] +#[diag(metadata_empty_link_name, code = E0454)] pub struct EmptyLinkName { #[primary_span] #[label] @@ -130,21 +130,21 @@ pub struct EmptyLinkName { } #[derive(Diagnostic)] -#[diag(metadata_link_framework_apple, code = "E0455")] +#[diag(metadata_link_framework_apple, code = E0455)] pub struct LinkFrameworkApple { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(metadata_framework_only_windows, code = "E0455")] +#[diag(metadata_framework_only_windows, code = E0455)] pub struct FrameworkOnlyWindows { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(metadata_unknown_link_kind, code = "E0458")] +#[diag(metadata_unknown_link_kind, code = E0458)] pub struct UnknownLinkKind<'a> { #[primary_span] #[label] @@ -239,7 +239,7 @@ pub struct IncompatibleWasmLink { } #[derive(Diagnostic)] -#[diag(metadata_link_requires_name, code = "E0459")] +#[diag(metadata_link_requires_name, code = E0459)] pub struct LinkRequiresName { #[primary_span] #[label] @@ -502,7 +502,7 @@ impl IntoDiagnostic<'_, G> for MultipleCandidates { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_multiple_candidates); diag.arg("crate_name", self.crate_name); diag.arg("flavor", self.flavor); - diag.code(error_code!(E0464)); + diag.code(E0464); diag.span(self.span); for (i, candidate) in self.candidates.iter().enumerate() { diag.note(format!("candidate #{}: {}", i + 1, candidate.display())); @@ -512,7 +512,7 @@ impl IntoDiagnostic<'_, G> for MultipleCandidates { } #[derive(Diagnostic)] -#[diag(metadata_symbol_conflicts_current, code = "E0519")] +#[diag(metadata_symbol_conflicts_current, code = E0519)] pub struct SymbolConflictsCurrent { #[primary_span] pub span: Span, @@ -537,7 +537,7 @@ pub struct DlError { } #[derive(Diagnostic)] -#[diag(metadata_newer_crate_version, code = "E0460")] +#[diag(metadata_newer_crate_version, code = E0460)] #[note] #[note(metadata_found_crate_versions)] pub struct NewerCrateVersion { @@ -549,7 +549,7 @@ pub struct NewerCrateVersion { } #[derive(Diagnostic)] -#[diag(metadata_no_crate_with_triple, code = "E0461")] +#[diag(metadata_no_crate_with_triple, code = E0461)] #[note(metadata_found_crate_versions)] pub struct NoCrateWithTriple<'a> { #[primary_span] @@ -561,7 +561,7 @@ pub struct NoCrateWithTriple<'a> { } #[derive(Diagnostic)] -#[diag(metadata_found_staticlib, code = "E0462")] +#[diag(metadata_found_staticlib, code = E0462)] #[note(metadata_found_crate_versions)] #[help] pub struct FoundStaticlib { @@ -573,7 +573,7 @@ pub struct FoundStaticlib { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_rustc, code = "E0514")] +#[diag(metadata_incompatible_rustc, code = E0514)] #[note(metadata_found_crate_versions)] #[help] pub struct IncompatibleRustc { @@ -598,7 +598,7 @@ impl IntoDiagnostic<'_, G> for InvalidMetadataFiles { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_invalid_meta_files); diag.arg("crate_name", self.crate_name); diag.arg("add_info", self.add_info); - diag.code(error_code!(E0786)); + diag.code(E0786); diag.span(self.span); for crate_rejection in self.crate_rejections { diag.note(crate_rejection); @@ -627,7 +627,7 @@ impl IntoDiagnostic<'_, G> for CannotFindCrate { diag.arg("current_crate", self.current_crate); diag.arg("add_info", self.add_info); diag.arg("locator_triple", self.locator_triple.triple()); - diag.code(error_code!(E0463)); + diag.code(E0463); diag.span(self.span); if (self.crate_name == sym::std || self.crate_name == sym::core) && self.locator_triple != TargetTriple::from_triple(config::host_triple()) diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 3c5536570872a..e0436b38c4be6 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -1,14 +1,14 @@ use std::borrow::Cow; use std::fmt; -use rustc_errors::{DiagnosticArgValue, DiagnosticMessage}; +use rustc_errors::{codes::*, DiagnosticArgValue, DiagnosticMessage}; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; use crate::ty::Ty; #[derive(Diagnostic)] -#[diag(middle_drop_check_overflow, code = "E0320")] +#[diag(middle_drop_check_overflow, code = E0320)] #[note] pub struct DropCheckOverflow<'tcx> { #[primary_span] diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 6a03bf243eb46..27b48f46e75a2 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -1,7 +1,7 @@ use crate::dep_graph::dep_kinds; use crate::query::plumbing::CyclePlaceholder; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan}; +use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_middle::ty::Representability; diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e1b998b24718c..6929c8040c503 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagnosticArgValue; use rustc_errors::{ - error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -138,7 +138,7 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = "E0133")] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = E0133)] #[note] pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { #[primary_span] @@ -150,7 +150,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)] #[note] pub struct CallToUnsafeFunctionRequiresUnsafeNameless { #[primary_span] @@ -161,7 +161,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNameless { } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[primary_span] @@ -175,7 +175,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[derive(Diagnostic)] #[diag( mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed, - code = "E0133" + code = E0133 )] #[note] pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { @@ -187,7 +187,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] -#[diag(mir_build_inline_assembly_requires_unsafe, code = "E0133")] +#[diag(mir_build_inline_assembly_requires_unsafe, code = E0133)] #[note] pub struct UseOfInlineAssemblyRequiresUnsafe { #[primary_span] @@ -198,7 +198,7 @@ pub struct UseOfInlineAssemblyRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -209,7 +209,7 @@ pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] -#[diag(mir_build_initializing_type_with_requires_unsafe, code = "E0133")] +#[diag(mir_build_initializing_type_with_requires_unsafe, code = E0133)] #[note] pub struct InitializingTypeWithRequiresUnsafe { #[primary_span] @@ -222,7 +222,7 @@ pub struct InitializingTypeWithRequiresUnsafe { #[derive(Diagnostic)] #[diag( mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, - code = "E0133" + code = E0133 )] #[note] pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { @@ -234,7 +234,7 @@ pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] -#[diag(mir_build_mutable_static_requires_unsafe, code = "E0133")] +#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] #[note] pub struct UseOfMutableStaticRequiresUnsafe { #[primary_span] @@ -245,7 +245,7 @@ pub struct UseOfMutableStaticRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -256,7 +256,7 @@ pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] -#[diag(mir_build_extern_static_requires_unsafe, code = "E0133")] +#[diag(mir_build_extern_static_requires_unsafe, code = E0133)] #[note] pub struct UseOfExternStaticRequiresUnsafe { #[primary_span] @@ -267,7 +267,7 @@ pub struct UseOfExternStaticRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -278,7 +278,7 @@ pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] -#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = "E0133")] +#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = E0133)] #[note] pub struct DerefOfRawPointerRequiresUnsafe { #[primary_span] @@ -289,7 +289,7 @@ pub struct DerefOfRawPointerRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -300,7 +300,7 @@ pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] -#[diag(mir_build_union_field_requires_unsafe, code = "E0133")] +#[diag(mir_build_union_field_requires_unsafe, code = E0133)] #[note] pub struct AccessToUnionFieldRequiresUnsafe { #[primary_span] @@ -311,7 +311,7 @@ pub struct AccessToUnionFieldRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] @@ -322,7 +322,7 @@ pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] -#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")] +#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = E0133)] #[note] pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] @@ -335,7 +335,7 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[derive(Diagnostic)] #[diag( mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, - code = "E0133" + code = E0133 )] #[note] pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { @@ -347,7 +347,7 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllow } #[derive(Diagnostic)] -#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")] +#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = E0133)] #[note] pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] @@ -360,7 +360,7 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[derive(Diagnostic)] #[diag( mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, - code = "E0133" + code = E0133 )] #[note] pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { @@ -372,7 +372,7 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed } #[derive(Diagnostic)] -#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")] +#[diag(mir_build_call_to_fn_with_requires_unsafe, code = E0133)] #[help] pub struct CallToFunctionWithRequiresUnsafe<'a> { #[primary_span] @@ -390,7 +390,7 @@ pub struct CallToFunctionWithRequiresUnsafe<'a> { } #[derive(Diagnostic)] -#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[help] pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[primary_span] @@ -468,7 +468,7 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { fluent::mir_build_non_exhaustive_patterns_type_not_empty, ); diag.span(self.span); - diag.code(error_code!(E0004)); + diag.code(E0004); let peeled_ty = self.ty.peel_refs(); diag.arg("ty", self.ty); diag.arg("peeled_ty", peeled_ty); @@ -539,28 +539,28 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { pub struct NonExhaustiveMatchAllArmsGuarded; #[derive(Diagnostic)] -#[diag(mir_build_static_in_pattern, code = "E0158")] +#[diag(mir_build_static_in_pattern, code = E0158)] pub struct StaticInPattern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_assoc_const_in_pattern, code = "E0158")] +#[diag(mir_build_assoc_const_in_pattern, code = E0158)] pub struct AssocConstInPattern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_param_in_pattern, code = "E0158")] +#[diag(mir_build_const_param_in_pattern, code = E0158)] pub struct ConstParamInPattern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_non_const_path, code = "E0080")] +#[diag(mir_build_non_const_path, code = E0080)] pub struct NonConstPath { #[primary_span] pub span: Span, @@ -590,7 +590,7 @@ pub struct CouldNotEvalConstPattern { } #[derive(Diagnostic)] -#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")] +#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = E0030)] pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper { #[primary_span] #[label] @@ -611,7 +611,7 @@ pub struct LiteralOutOfRange<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")] +#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = E0579)] pub struct LowerRangeBoundMustBeLessThanUpper { #[primary_span] pub span: Span, @@ -634,7 +634,7 @@ pub struct TrailingIrrefutableLetPatterns { } #[derive(LintDiagnostic)] -#[diag(mir_build_bindings_with_variant_name, code = "E0170")] +#[diag(mir_build_bindings_with_variant_name, code = E0170)] pub struct BindingsWithVariantName { #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")] pub suggestion: Option, @@ -821,7 +821,7 @@ pub struct NonPartialEqMatch<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_pattern_not_covered, code = "E0005")] +#[diag(mir_build_pattern_not_covered, code = E0005)] pub(crate) struct PatternNotCovered<'s, 'tcx> { #[primary_span] pub span: Span, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 435ea3dc3bbc7..caf7f4227dbf8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -11,7 +11,7 @@ use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, + codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::*; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index ff7e985bdfdcc..2190ad14b5511 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -8,7 +8,7 @@ pub(crate) use self::check_match::check_match; use crate::errors::*; use crate::thir::util::UserAnnotatedTyHelpers; -use rustc_errors::error_code; +use rustc_errors::codes::*; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; @@ -209,7 +209,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { RangeEnd::Included => { self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper { span, - teach: self.tcx.sess.teach(&error_code!(E0030)).then_some(()), + teach: self.tcx.sess.teach(E0030).then_some(()), }) } RangeEnd::Excluded => { diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 4574cb4d28d25..4ef3d47d6a6f5 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use rustc_errors::{ - Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, + codes::*, Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -33,7 +33,7 @@ pub(crate) enum ConstMutate { } #[derive(Diagnostic)] -#[diag(mir_transform_unaligned_packed_ref, code = "E0793")] +#[diag(mir_transform_unaligned_packed_ref, code = E0793)] #[note] #[note(mir_transform_note_ub)] #[help] @@ -66,7 +66,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); - diag.code("E0133".to_string()); + diag.code(E0133); diag.span(self.span); diag.span_label(self.span, self.details.label()); let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 40852048293a9..053a9c03d7483 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; use rustc_errors::{ - AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -25,7 +25,7 @@ pub(crate) struct AmbiguousPlus { } #[derive(Diagnostic)] -#[diag(parse_maybe_recover_from_bad_type_plus, code = "E0178")] +#[diag(parse_maybe_recover_from_bad_type_plus, code = E0178)] pub(crate) struct BadTypePlus { pub ty: String, #[primary_span] @@ -807,7 +807,7 @@ pub(crate) struct InclusiveRangeMatchArrow { } #[derive(Diagnostic)] -#[diag(parse_inclusive_range_no_end, code = "E0586")] +#[diag(parse_inclusive_range_no_end, code = E0586)] #[note] pub(crate) struct InclusiveRangeNoEnd { #[primary_span] @@ -901,7 +901,7 @@ pub(crate) struct MismatchedClosingDelimiter { } #[derive(Diagnostic)] -#[diag(parse_incorrect_visibility_restriction, code = "E0704")] +#[diag(parse_incorrect_visibility_restriction, code = E0704)] #[help] pub(crate) struct IncorrectVisibilityRestriction { #[primary_span] @@ -925,7 +925,7 @@ pub(crate) struct ExpectedStatementAfterOuterAttr { } #[derive(Diagnostic)] -#[diag(parse_doc_comment_does_not_document_anything, code = "E0585")] +#[diag(parse_doc_comment_does_not_document_anything, code = E0585)] #[help] pub(crate) struct DocCommentDoesNotDocumentAnything { #[primary_span] @@ -1357,7 +1357,7 @@ pub(crate) struct AttributeOnParamType { } #[derive(Diagnostic)] -#[diag(parse_pattern_method_param_without_body, code = "E0642")] +#[diag(parse_pattern_method_param_without_body, code = E0642)] pub(crate) struct PatternMethodParamWithoutBody { #[primary_span] #[suggestion(code = "_", applicability = "machine-applicable")] @@ -1565,7 +1565,7 @@ pub(crate) struct WhereClauseBeforeTupleStructBodySugg { } #[derive(Diagnostic)] -#[diag(parse_async_fn_in_2015, code = "E0670")] +#[diag(parse_async_fn_in_2015, code = E0670)] pub(crate) struct AsyncFnIn2015 { #[primary_span] #[label] @@ -1929,7 +1929,7 @@ pub struct CrDocComment { } #[derive(Diagnostic)] -#[diag(parse_no_digits_literal, code = "E0768")] +#[diag(parse_no_digits_literal, code = E0768)] pub struct NoDigitsLiteral { #[primary_span] pub span: Span, @@ -2499,7 +2499,7 @@ pub(crate) struct FnPointerCannotBeAsync { } #[derive(Diagnostic)] -#[diag(parse_nested_c_variadic_type, code = "E0743")] +#[diag(parse_nested_c_variadic_type, code = E0743)] pub(crate) struct NestedCVariadicType { #[primary_span] pub span: Span, diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 20ec4a300c1f8..3155245267600 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,7 +7,7 @@ use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; -use rustc_errors::{error_code, Applicability, DiagCtxt, DiagnosticBuilder, StashKey}; +use rustc_errors::{codes::*, Applicability, DiagCtxt, DiagnosticBuilder, StashKey}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -397,7 +397,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { if !terminated { self.dcx() .struct_span_fatal(self.mk_sp(start, end), "unterminated character literal") - .with_code(error_code!(E0762)) + .with_code(E0762) .emit() } self.cook_unicode(token::Char, Mode::Char, start, end, 1, 1) // ' ' @@ -409,7 +409,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { self.mk_sp(start + BytePos(1), end), "unterminated byte constant", ) - .with_code(error_code!(E0763)) + .with_code(E0763) .emit() } self.cook_unicode(token::Byte, Mode::Byte, start, end, 2, 1) // b' ' @@ -421,7 +421,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { self.mk_sp(start, end), "unterminated double quote string", ) - .with_code(error_code!(E0765)) + .with_code(E0765) .emit() } self.cook_unicode(token::Str, Mode::Str, start, end, 1, 1) // " " @@ -433,7 +433,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { self.mk_sp(start + BytePos(1), end), "unterminated double quote byte string", ) - .with_code(error_code!(E0766)) + .with_code(E0766) .emit() } self.cook_unicode(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" " @@ -445,7 +445,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { self.mk_sp(start + BytePos(1), end), "unterminated C string", ) - .with_code(error_code!(E0767)) + .with_code(E0767) .emit() } self.cook_mixed(token::CStr, Mode::CStr, start, end, 2, 1) // c" " @@ -582,7 +582,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { ) -> ! { let mut err = self.dcx().struct_span_fatal(self.mk_sp(start, start), "unterminated raw string"); - err.code(error_code!(E0748)); + err.code(E0748); err.span_label(self.mk_sp(start, start), "unterminated raw string"); if n_hashes > 0 { @@ -614,7 +614,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { }; let last_bpos = self.pos; let mut err = self.dcx().struct_span_fatal(self.mk_sp(start, last_bpos), msg); - err.code(error_code!(E0758)); + err.code(E0758); let mut nested_block_comment_open_idxs = vec![]; let mut last_nested_block_comment_idxs = None; let mut content_chars = self.str_from(start).char_indices().peekable(); diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index a92609c2c2f87..98e062dd784d4 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -8,7 +8,7 @@ use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; -use rustc_errors::{error_code, Diagnostic, PResult}; +use rustc_errors::{codes::*, Diagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; @@ -61,7 +61,7 @@ impl<'a> Parser<'a> { let mut err = self .dcx() .struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted); - err.code(error_code!(E0753)); + err.code(E0753); if let Some(replacement_span) = self.annotate_following_item_if_applicable( &mut err, span, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3bd8ae0258628..9a77643f9510f 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -10,7 +10,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; -use rustc_errors::{struct_span_code_err, Applicability, PResult, StashKey}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability, PResult, StashKey}; use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; use rustc_span::source_map; diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 25ca685cbfade..97c70e327f0fe 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,6 +1,6 @@ use rustc_ast::attr; use rustc_ast::entry::EntryPointType; -use rustc_errors::error_code; +use rustc_errors::codes::*; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{ItemId, Node, CRATE_HIR_ID}; @@ -180,8 +180,8 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) { Default::default() }); let main_def_opt = tcx.resolutions(()).main_def; - let code = error_code!(E0601); - let add_teach_note = tcx.sess.teach(&code); + let code = E0601; + let add_teach_note = tcx.sess.teach(code); // The file may be empty, which leads to the diagnostic machinery not emitting this // note. This is a relatively simple way to detect that case and emit a span-less // note instead. diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index cf3c7cc4ace0d..77bfe57e3706f 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -6,7 +6,7 @@ use std::{ use crate::fluent_generated as fluent; use rustc_ast::Label; use rustc_errors::{ - error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, }; use rustc_hir::{self as hir, ExprKind, Target}; @@ -55,7 +55,7 @@ pub struct IgnoredInlineAttrFnProto; pub struct IgnoredInlineAttrConstants; #[derive(Diagnostic)] -#[diag(passes_inline_not_fn_or_closure, code = "E0518")] +#[diag(passes_inline_not_fn_or_closure, code = E0518)] pub struct InlineNotFnOrClosure { #[primary_span] pub attr_span: Span, @@ -76,7 +76,7 @@ pub struct IgnoredCoveragePropagate; pub struct IgnoredCoverageFnDefn; #[derive(Diagnostic)] -#[diag(passes_coverage_not_coverable, code = "E0788")] +#[diag(passes_coverage_not_coverable, code = E0788)] pub struct IgnoredCoverageNotCoverable { #[primary_span] pub attr_span: Span, @@ -95,14 +95,14 @@ pub struct AttrShouldBeAppliedToFn { } #[derive(Diagnostic)] -#[diag(passes_naked_tracked_caller, code = "E0736")] +#[diag(passes_naked_tracked_caller, code = E0736)] pub struct NakedTrackedCaller { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(passes_should_be_applied_to_fn, code = "E0739")] +#[diag(passes_should_be_applied_to_fn, code = E0739)] pub struct TrackedCallerWrongLocation { #[primary_span] pub attr_span: Span, @@ -112,7 +112,7 @@ pub struct TrackedCallerWrongLocation { } #[derive(Diagnostic)] -#[diag(passes_should_be_applied_to_struct_enum, code = "E0701")] +#[diag(passes_should_be_applied_to_struct_enum, code = E0701)] pub struct NonExhaustiveWrongLocation { #[primary_span] pub attr_span: Span, @@ -370,28 +370,28 @@ pub struct HasIncoherentInherentImpl { } #[derive(Diagnostic)] -#[diag(passes_both_ffi_const_and_pure, code = "E0757")] +#[diag(passes_both_ffi_const_and_pure, code = E0757)] pub struct BothFfiConstAndPure { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(passes_ffi_pure_invalid_target, code = "E0755")] +#[diag(passes_ffi_pure_invalid_target, code = E0755)] pub struct FfiPureInvalidTarget { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(passes_ffi_const_invalid_target, code = "E0756")] +#[diag(passes_ffi_const_invalid_target, code = E0756)] pub struct FfiConstInvalidTarget { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(passes_ffi_returns_twice_invalid_target, code = "E0724")] +#[diag(passes_ffi_returns_twice_invalid_target, code = E0724)] pub struct FfiReturnsTwiceInvalidTarget { #[primary_span] pub attr_span: Span, @@ -552,21 +552,21 @@ pub struct NoMangle { } #[derive(Diagnostic)] -#[diag(passes_repr_ident, code = "E0565")] +#[diag(passes_repr_ident, code = E0565)] pub struct ReprIdent { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_repr_conflicting, code = "E0566")] +#[diag(passes_repr_conflicting, code = E0566)] pub struct ReprConflicting { #[primary_span] pub hint_spans: Vec, } #[derive(LintDiagnostic)] -#[diag(passes_repr_conflicting, code = "E0566")] +#[diag(passes_repr_conflicting, code = E0566)] pub struct ReprConflictingLint; #[derive(Diagnostic)] @@ -667,7 +667,7 @@ pub(crate) struct EmptyConfusables { } #[derive(Diagnostic)] -#[diag(passes_incorrect_meta_item, code = "E0539")] +#[diag(passes_incorrect_meta_item, code = E0539)] pub(crate) struct IncorrectMetaItem { #[primary_span] pub span: Span, @@ -737,7 +737,7 @@ pub struct Unused { } #[derive(Diagnostic)] -#[diag(passes_non_exported_macro_invalid_attrs, code = "E0518")] +#[diag(passes_non_exported_macro_invalid_attrs, code = E0518)] pub struct NonExportedMacroInvalidAttrs { #[primary_span] #[label] @@ -801,7 +801,7 @@ pub struct DeprecatedAnnotationHasNoEffect { } #[derive(Diagnostic)] -#[diag(passes_unknown_external_lang_item, code = "E0264")] +#[diag(passes_unknown_external_lang_item, code = E0264)] pub struct UnknownExternLangItem { #[primary_span] pub span: Span, @@ -837,7 +837,7 @@ pub struct LangItemWithTargetFeature { } #[derive(Diagnostic)] -#[diag(passes_lang_item_on_incorrect_target, code = "E0718")] +#[diag(passes_lang_item_on_incorrect_target, code = E0718)] pub struct LangItemOnIncorrectTarget { #[primary_span] #[label] @@ -848,7 +848,7 @@ pub struct LangItemOnIncorrectTarget { } #[derive(Diagnostic)] -#[diag(passes_unknown_lang_item, code = "E0522")] +#[diag(passes_unknown_lang_item, code = E0522)] pub struct UnknownLangItem { #[primary_span] #[label] @@ -990,7 +990,7 @@ pub struct UnrecognizedField { } #[derive(Diagnostic)] -#[diag(passes_feature_stable_twice, code = "E0711")] +#[diag(passes_feature_stable_twice, code = E0711)] pub struct FeatureStableTwice { #[primary_span] pub span: Span, @@ -1000,7 +1000,7 @@ pub struct FeatureStableTwice { } #[derive(Diagnostic)] -#[diag(passes_feature_previously_declared, code = "E0711")] +#[diag(passes_feature_previously_declared, code = E0711)] pub struct FeaturePreviouslyDeclared<'a, 'b> { #[primary_span] pub span: Span, @@ -1025,7 +1025,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_break_non_loop); diag.span(self.span); - diag.code(error_code!(E0571)); + diag.code(E0571); diag.arg("kind", self.kind); diag.span_label(self.span, fluent::passes_label); if let Some(head) = self.head { @@ -1063,7 +1063,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { } #[derive(Diagnostic)] -#[diag(passes_continue_labeled_block, code = "E0696")] +#[diag(passes_continue_labeled_block, code = E0696)] pub struct ContinueLabeledBlock { #[primary_span] #[label] @@ -1073,7 +1073,7 @@ pub struct ContinueLabeledBlock { } #[derive(Diagnostic)] -#[diag(passes_break_inside_closure, code = "E0267")] +#[diag(passes_break_inside_closure, code = E0267)] pub struct BreakInsideClosure<'a> { #[primary_span] #[label] @@ -1084,7 +1084,7 @@ pub struct BreakInsideClosure<'a> { } #[derive(Diagnostic)] -#[diag(passes_break_inside_async_block, code = "E0267")] +#[diag(passes_break_inside_async_block, code = E0267)] pub struct BreakInsideAsyncBlock<'a> { #[primary_span] #[label] @@ -1095,7 +1095,7 @@ pub struct BreakInsideAsyncBlock<'a> { } #[derive(Diagnostic)] -#[diag(passes_outside_loop, code = "E0268")] +#[diag(passes_outside_loop, code = E0268)] pub struct OutsideLoop<'a> { #[primary_span] #[label] @@ -1115,7 +1115,7 @@ pub struct OutsideLoopSuggestion { } #[derive(Diagnostic)] -#[diag(passes_unlabeled_in_labeled_block, code = "E0695")] +#[diag(passes_unlabeled_in_labeled_block, code = E0695)] pub struct UnlabeledInLabeledBlock<'a> { #[primary_span] #[label] @@ -1124,7 +1124,7 @@ pub struct UnlabeledInLabeledBlock<'a> { } #[derive(Diagnostic)] -#[diag(passes_unlabeled_cf_in_while_condition, code = "E0590")] +#[diag(passes_unlabeled_cf_in_while_condition, code = E0590)] pub struct UnlabeledCfInWhileCondition<'a> { #[primary_span] #[label] @@ -1169,7 +1169,7 @@ impl IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock { fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_naked_functions_asm_block); diag.span(self.span); - diag.code(error_code!(E0787)); + diag.code(E0787); for span in self.multiple_asms.iter() { diag.span_label(*span, fluent::passes_label_multiple_asm); } @@ -1181,14 +1181,14 @@ impl IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock { } #[derive(Diagnostic)] -#[diag(passes_naked_functions_operands, code = "E0787")] +#[diag(passes_naked_functions_operands, code = E0787)] pub struct NakedFunctionsOperands { #[primary_span] pub unsupported_operands: Vec, } #[derive(Diagnostic)] -#[diag(passes_naked_functions_asm_options, code = "E0787")] +#[diag(passes_naked_functions_asm_options, code = E0787)] pub struct NakedFunctionsAsmOptions { #[primary_span] pub span: Span, @@ -1196,7 +1196,7 @@ pub struct NakedFunctionsAsmOptions { } #[derive(Diagnostic)] -#[diag(passes_naked_functions_must_use_noreturn, code = "E0787")] +#[diag(passes_naked_functions_must_use_noreturn, code = E0787)] pub struct NakedFunctionsMustUseNoreturn { #[primary_span] pub span: Span, @@ -1229,7 +1229,7 @@ pub struct AttrOnlyInFunctions { } #[derive(Diagnostic)] -#[diag(passes_multiple_rustc_main, code = "E0137")] +#[diag(passes_multiple_rustc_main, code = E0137)] pub struct MultipleRustcMain { #[primary_span] pub span: Span, @@ -1240,7 +1240,7 @@ pub struct MultipleRustcMain { } #[derive(Diagnostic)] -#[diag(passes_multiple_start_functions, code = "E0138")] +#[diag(passes_multiple_start_functions, code = E0138)] pub struct MultipleStartFunctions { #[primary_span] pub span: Span, @@ -1280,7 +1280,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_no_main_function); diag.span(DUMMY_SP); - diag.code(error_code!(E0601)); + diag.code(E0601); diag.arg("crate_name", self.crate_name); diag.arg("filename", self.filename); diag.arg("has_filename", self.has_filename); @@ -1345,7 +1345,7 @@ impl IntoDiagnostic<'_, G> for DuplicateLangItem { Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends, }, ); - diag.code(error_code!(E0152)); + diag.code(E0152); diag.arg("lang_item_name", self.lang_item_name); diag.arg("crate_name", self.crate_name); diag.arg("dependency_of", self.dependency_of); @@ -1382,7 +1382,7 @@ impl IntoDiagnostic<'_, G> for DuplicateLangItem { } #[derive(Diagnostic)] -#[diag(passes_incorrect_target, code = "E0718")] +#[diag(passes_incorrect_target, code = E0718)] pub struct IncorrectTarget<'a> { #[primary_span] pub span: Span, @@ -1418,7 +1418,7 @@ pub struct ObjectLifetimeErr { } #[derive(Diagnostic)] -#[diag(passes_unrecognized_repr_hint, code = "E0552")] +#[diag(passes_unrecognized_repr_hint, code = E0552)] #[help] pub struct UnrecognizedReprHint { #[primary_span] @@ -1427,35 +1427,35 @@ pub struct UnrecognizedReprHint { #[derive(Diagnostic)] pub enum AttrApplication { - #[diag(passes_attr_application_enum, code = "E0517")] + #[diag(passes_attr_application_enum, code = E0517)] Enum { #[primary_span] hint_span: Span, #[label] span: Span, }, - #[diag(passes_attr_application_struct, code = "E0517")] + #[diag(passes_attr_application_struct, code = E0517)] Struct { #[primary_span] hint_span: Span, #[label] span: Span, }, - #[diag(passes_attr_application_struct_union, code = "E0517")] + #[diag(passes_attr_application_struct_union, code = E0517)] StructUnion { #[primary_span] hint_span: Span, #[label] span: Span, }, - #[diag(passes_attr_application_struct_enum_union, code = "E0517")] + #[diag(passes_attr_application_struct_enum_union, code = E0517)] StructEnumUnion { #[primary_span] hint_span: Span, #[label] span: Span, }, - #[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")] + #[diag(passes_attr_application_struct_enum_function_method_union, code = E0517)] StructEnumFunctionMethodUnion { #[primary_span] hint_span: Span, @@ -1465,7 +1465,7 @@ pub enum AttrApplication { } #[derive(Diagnostic)] -#[diag(passes_transparent_incompatible, code = "E0692")] +#[diag(passes_transparent_incompatible, code = E0692)] pub struct TransparentIncompatible { #[primary_span] pub hint_spans: Vec, @@ -1473,7 +1473,7 @@ pub struct TransparentIncompatible { } #[derive(Diagnostic)] -#[diag(passes_deprecated_attribute, code = "E0549")] +#[diag(passes_deprecated_attribute, code = E0549)] pub struct DeprecatedAttribute { #[primary_span] pub span: Span, @@ -1524,7 +1524,7 @@ pub struct TraitImplConstStable { } #[derive(Diagnostic)] -#[diag(passes_feature_only_on_nightly, code = "E0554")] +#[diag(passes_feature_only_on_nightly, code = E0554)] pub struct FeatureOnlyOnNightly { #[primary_span] pub span: Span, @@ -1532,7 +1532,7 @@ pub struct FeatureOnlyOnNightly { } #[derive(Diagnostic)] -#[diag(passes_unknown_feature, code = "E0635")] +#[diag(passes_unknown_feature, code = E0635)] pub struct UnknownFeature { #[primary_span] pub span: Span, @@ -1549,7 +1549,7 @@ pub struct ImpliedFeatureNotExist { } #[derive(Diagnostic)] -#[diag(passes_duplicate_feature_err, code = "E0636")] +#[diag(passes_duplicate_feature_err, code = E0636)] pub struct DuplicateFeatureErr { #[primary_span] pub span: Span, diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index b1242f82f4fec..01c6d18c0e1be 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -1,9 +1,9 @@ -use rustc_errors::DiagnosticArgFromDisplay; +use rustc_errors::{codes::*, DiagnosticArgFromDisplay}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(privacy_field_is_private, code = "E0451")] +#[diag(privacy_field_is_private, code = E0451)] pub struct FieldIsPrivate { #[primary_span] pub span: Span, @@ -48,7 +48,7 @@ pub struct UnnamedItemIsPrivate { } #[derive(Diagnostic)] -#[diag(privacy_in_public_interface, code = "E0446")] +#[diag(privacy_in_public_interface, code = E0446)] pub struct InPublicInterface<'a> { #[primary_span] #[label] diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 5829e17ec1625..9db6fac8036a9 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -1,3 +1,4 @@ +use rustc_errors::codes::*; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::Limit; use rustc_span::{Span, Symbol}; @@ -45,7 +46,7 @@ pub struct CycleUsage { } #[derive(Diagnostic)] -#[diag(query_system_cycle, code = "E0391")] +#[diag(query_system_cycle, code = E0391)] pub struct Cycle { #[primary_span] pub span: Span, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index b855ec8f920b2..7eb7c8c2bca22 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -19,7 +19,7 @@ use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; use rustc_attr as attr; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_code_err, Applicability}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability}; use rustc_expand::expand::AstFragment; use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 66dfee6c062d8..f3a6eb65a7235 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -6,8 +6,8 @@ use rustc_ast::{MetaItemKind, NestedMetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - pluralize, report_ambiguity_error, struct_span_code_err, Applicability, DiagCtxt, Diagnostic, - DiagnosticBuilder, ErrorGuaranteed, MultiSpan, SuggestionStyle, + codes::*, pluralize, report_ambiguity_error, struct_span_code_err, Applicability, DiagCtxt, + Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, SuggestionStyle, }; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 5d9269d8f542c..50ff09feb4d9b 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,3 +1,4 @@ +use rustc_errors::codes::*; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{ symbol::{Ident, Symbol}, @@ -7,16 +8,16 @@ use rustc_span::{ use crate::{late::PatternSource, Res}; #[derive(Diagnostic)] -#[diag(resolve_parent_module_reset_for_binding, code = "E0637")] +#[diag(resolve_parent_module_reset_for_binding, code = E0637)] pub(crate) struct ParentModuleResetForBinding; #[derive(Diagnostic)] -#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = "E0637")] +#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = E0637)] #[note] pub(crate) struct AmpersandUsedWithoutExplicitLifetimeName(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = "E0637")] +#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = E0637)] #[note] pub(crate) struct UnderscoreLifetimeNameCannotBeUsedHere(#[primary_span] pub(crate) Span); @@ -33,7 +34,7 @@ pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate) pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_generic_params_from_outer_item, code = "E0401")] +#[diag(resolve_generic_params_from_outer_item, code = E0401)] pub(crate) struct GenericParamsFromOuterItem { #[primary_span] #[label] @@ -67,7 +68,7 @@ pub(crate) struct GenericParamsFromOuterItemSugg { } #[derive(Diagnostic)] -#[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")] +#[diag(resolve_name_is_already_used_as_generic_parameter, code = E0403)] pub(crate) struct NameAlreadyUsedInParameterList { #[primary_span] #[label] @@ -78,7 +79,7 @@ pub(crate) struct NameAlreadyUsedInParameterList { } #[derive(Diagnostic)] -#[diag(resolve_method_not_member_of_trait, code = "E0407")] +#[diag(resolve_method_not_member_of_trait, code = E0407)] pub(crate) struct MethodNotMemberOfTrait { #[primary_span] #[label] @@ -102,7 +103,7 @@ pub(crate) struct AssociatedFnWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_type_not_member_of_trait, code = "E0437")] +#[diag(resolve_type_not_member_of_trait, code = E0437)] pub(crate) struct TypeNotMemberOfTrait { #[primary_span] #[label] @@ -126,7 +127,7 @@ pub(crate) struct AssociatedTypeWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_const_not_member_of_trait, code = "E0438")] +#[diag(resolve_const_not_member_of_trait, code = E0438)] pub(crate) struct ConstNotMemberOfTrait { #[primary_span] #[label] @@ -150,7 +151,7 @@ pub(crate) struct AssociatedConstWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_variable_bound_with_different_mode, code = "E0409")] +#[diag(resolve_variable_bound_with_different_mode, code = E0409)] pub(crate) struct VariableBoundWithDifferentMode { #[primary_span] #[label] @@ -161,7 +162,7 @@ pub(crate) struct VariableBoundWithDifferentMode { } #[derive(Diagnostic)] -#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = "E0415")] +#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = E0415)] pub(crate) struct IdentifierBoundMoreThanOnceInParameterList { #[primary_span] #[label] @@ -170,7 +171,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInParameterList { } #[derive(Diagnostic)] -#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = "E0416")] +#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = E0416)] pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern { #[primary_span] #[label] @@ -179,7 +180,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern { } #[derive(Diagnostic)] -#[diag(resolve_undeclared_label, code = "E0426")] +#[diag(resolve_undeclared_label, code = E0426)] pub(crate) struct UndeclaredLabel { #[primary_span] #[label] @@ -217,7 +218,7 @@ pub(crate) struct UnreachableLabelWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = "E0430")] +#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = E0430)] pub(crate) struct SelfImportCanOnlyAppearOnceInTheList { #[primary_span] #[label] @@ -225,7 +226,7 @@ pub(crate) struct SelfImportCanOnlyAppearOnceInTheList { } #[derive(Diagnostic)] -#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = "E0431")] +#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = E0431)] pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix { #[primary_span] #[label] @@ -233,7 +234,7 @@ pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix { } #[derive(Diagnostic)] -#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = "E0434")] +#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)] #[help] pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem { #[primary_span] @@ -241,7 +242,7 @@ pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem { } #[derive(Diagnostic)] -#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = "E0435")] +#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = E0435)] pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> { #[primary_span] pub(crate) span: Span, @@ -283,7 +284,7 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> { } #[derive(Diagnostic)] -#[diag(resolve_self_imports_only_allowed_within, code = "E0429")] +#[diag(resolve_self_imports_only_allowed_within, code = E0429)] pub(crate) struct SelfImportsOnlyAllowedWithin { #[primary_span] pub(crate) span: Span, @@ -317,7 +318,7 @@ pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_binding_shadows_something_unacceptable, code = "E0530")] +#[diag(resolve_binding_shadows_something_unacceptable, code = E0530)] pub(crate) struct BindingShadowsSomethingUnacceptable<'a> { #[primary_span] #[label] @@ -346,7 +347,7 @@ pub(crate) struct BindingShadowsSomethingUnacceptableSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_forward_declared_generic_param, code = "E0128")] +#[diag(resolve_forward_declared_generic_param, code = E0128)] pub(crate) struct ForwardDeclaredGenericParam { #[primary_span] #[label] @@ -354,7 +355,7 @@ pub(crate) struct ForwardDeclaredGenericParam { } #[derive(Diagnostic)] -#[diag(resolve_param_in_ty_of_const_param, code = "E0770")] +#[diag(resolve_param_in_ty_of_const_param, code = E0770)] pub(crate) struct ParamInTyOfConstParam { #[primary_span] #[label] @@ -376,7 +377,7 @@ pub(crate) enum ParamKindInTyOfConstParam { } #[derive(Diagnostic)] -#[diag(resolve_self_in_generic_param_default, code = "E0735")] +#[diag(resolve_self_in_generic_param_default, code = E0735)] pub(crate) struct SelfInGenericParamDefault { #[primary_span] #[label] @@ -412,7 +413,7 @@ pub(crate) enum ParamKindInNonTrivialAnonConst { } #[derive(Diagnostic)] -#[diag(resolve_unreachable_label, code = "E0767")] +#[diag(resolve_unreachable_label, code = E0767)] #[note] pub(crate) struct UnreachableLabel { #[primary_span] @@ -495,7 +496,7 @@ pub(crate) struct BindingInNeverPattern { } #[derive(Diagnostic)] -#[diag(resolve_trait_impl_duplicate, code = "E0201")] +#[diag(resolve_trait_impl_duplicate, code = E0201)] pub(crate) struct TraitImplDuplicate { #[primary_span] #[label] @@ -518,11 +519,11 @@ pub(crate) struct Relative2018 { } #[derive(Diagnostic)] -#[diag(resolve_ancestor_only, code = "E0742")] +#[diag(resolve_ancestor_only, code = E0742)] pub(crate) struct AncestorOnly(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_expected_found, code = "E0577")] +#[diag(resolve_expected_found, code = E0577)] pub(crate) struct ExpectedFound { #[primary_span] #[label] @@ -532,7 +533,7 @@ pub(crate) struct ExpectedFound { } #[derive(Diagnostic)] -#[diag(resolve_indeterminate, code = "E0578")] +#[diag(resolve_indeterminate, code = E0578)] pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] @@ -714,7 +715,7 @@ pub(crate) struct CannotDetermineMacroResolution { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_private, code = "E0364")] +#[diag(resolve_cannot_be_reexported_private, code = E0364)] pub(crate) struct CannotBeReexportedPrivate { #[primary_span] pub(crate) span: Span, @@ -722,7 +723,7 @@ pub(crate) struct CannotBeReexportedPrivate { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_crate_public, code = "E0364")] +#[diag(resolve_cannot_be_reexported_crate_public, code = E0364)] pub(crate) struct CannotBeReexportedCratePublic { #[primary_span] pub(crate) span: Span, @@ -730,7 +731,7 @@ pub(crate) struct CannotBeReexportedCratePublic { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_private, code = "E0365")] +#[diag(resolve_cannot_be_reexported_private, code = E0365)] #[note(resolve_consider_declaring_with_pub)] pub(crate) struct CannotBeReexportedPrivateNS { #[primary_span] @@ -740,7 +741,7 @@ pub(crate) struct CannotBeReexportedPrivateNS { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_crate_public, code = "E0365")] +#[diag(resolve_cannot_be_reexported_crate_public, code = E0365)] #[note(resolve_consider_declaring_with_pub)] pub(crate) struct CannotBeReexportedCratePublicNS { #[primary_span] @@ -779,7 +780,7 @@ pub(crate) struct ItemsInTraitsAreNotImportable { } #[derive(Diagnostic)] -#[diag(resolve_is_not_directly_importable, code = "E0253")] +#[diag(resolve_is_not_directly_importable, code = E0253)] pub(crate) struct IsNotDirectlyImportable { #[primary_span] #[label] diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index ad60caed354fc..30fb35238c3c7 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -17,7 +17,7 @@ use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult}; use rustc_ast::NodeId; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::intern::Interned; -use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan}; +use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan}; use rustc_hir::def::{self, DefKind, PartialRes}; use rustc_middle::metadata::ModChild; use rustc_middle::metadata::Reexport; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 18926463d6b04..0743ff0386402 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -16,7 +16,9 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::{Applicability, DiagnosticArgValue, IntoDiagnosticArg}; +use rustc_errors::{ + codes::*, struct_span_code_err, Applicability, DiagnosticArgValue, ErrCode, IntoDiagnosticArg, +}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -533,21 +535,20 @@ impl<'a> PathSource<'a> { } } - fn error_code(self, has_unexpected_resolution: bool) -> String { - use rustc_errors::error_code; + fn error_code(self, has_unexpected_resolution: bool) -> ErrCode { match (self, has_unexpected_resolution) { - (PathSource::Trait(_), true) => error_code!(E0404), - (PathSource::Trait(_), false) => error_code!(E0405), - (PathSource::Type, true) => error_code!(E0573), - (PathSource::Type, false) => error_code!(E0412), - (PathSource::Struct, true) => error_code!(E0574), - (PathSource::Struct, false) => error_code!(E0422), - (PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423), - (PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425), - (PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532), - (PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531), - (PathSource::TraitItem(..), true) => error_code!(E0575), - (PathSource::TraitItem(..), false) => error_code!(E0576), + (PathSource::Trait(_), true) => E0404, + (PathSource::Trait(_), false) => E0405, + (PathSource::Type, true) => E0573, + (PathSource::Type, false) => E0412, + (PathSource::Struct, true) => E0574, + (PathSource::Struct, false) => E0422, + (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423, + (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425, + (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532, + (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531, + (PathSource::TraitItem(..), true) => E0575, + (PathSource::TraitItem(..), false) => E0576, } } } @@ -1673,13 +1674,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } else { ("`'_` cannot be used here", "`'_` is a reserved lifetime name") }; - let mut diag = rustc_errors::struct_span_code_err!( - self.r.dcx(), - lifetime.ident.span, - E0637, - "{}", - msg, - ); + let mut diag = + struct_span_code_err!(self.r.dcx(), lifetime.ident.span, E0637, "{}", msg,); diag.span_label(lifetime.ident.span, note); if elided { for rib in self.lifetime_ribs[i..].iter().rev() { @@ -1863,7 +1859,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } | LifetimeRibKind::AnonymousWarn(_) => { let sess = self.r.tcx.sess; - let mut err = rustc_errors::struct_span_code_err!( + let mut err = struct_span_code_err!( sess.dcx(), path_span, E0726, @@ -2608,7 +2604,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if param.ident.name == kw::UnderscoreLifetime { - rustc_errors::struct_span_code_err!( + struct_span_code_err!( self.r.dcx(), param.ident.span, E0637, @@ -2622,7 +2618,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if param.ident.name == kw::StaticLifetime { - rustc_errors::struct_span_code_err!( + struct_span_code_err!( self.r.dcx(), param.ident.span, E0262, @@ -3164,10 +3160,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // The method kind does not correspond to what appeared in the trait, report. let path = &self.current_trait_ref.as_ref().unwrap().1.path; let (code, kind) = match kind { - AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"), - AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"), - AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"), - AssocItemKind::Delegation(..) => (rustc_errors::error_code!(E0324), "method"), + AssocItemKind::Const(..) => (E0323, "const"), + AssocItemKind::Fn(..) => (E0324, "method"), + AssocItemKind::Type(..) => (E0325, "type"), + AssocItemKind::Delegation(..) => (E0324, "method"), AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"), }; let trait_path = path_names_to_string(path); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index abb0a7a465aa1..a4c041f1ff247 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -16,8 +16,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust::where_bound_predicate_to_string; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, - MultiSpan, SuggestionStyle, + codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, MultiSpan, SuggestionStyle, }; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind}; @@ -922,8 +922,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { path: &[Segment], span: Span, ) { - if let Some(err_code) = &err.code { - if err_code == &rustc_errors::error_code!(E0425) { + if let Some(err_code) = err.code { + if err_code == E0425 { for label_rib in &self.label_ribs { for (label_ident, node_id) in &label_rib.bindings { let ident = path.last().unwrap().ident; @@ -946,7 +946,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } } - } else if err_code == &rustc_errors::error_code!(E0412) { + } else if err_code == E0412 { if let Some(correct) = Self::likely_rust_type(path) { err.span_suggestion( span, @@ -970,7 +970,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { if !is_self_type(path, source.namespace()) { return false; } - err.code(rustc_errors::error_code!(E0411)); + err.code(E0411); err.span_label(span, "`Self` is only available in impls, traits, and type definitions"); if let Some(item_kind) = self.diagnostic_metadata.current_item { if !item_kind.ident.span.is_dummy() { @@ -999,7 +999,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } debug!("smart_resolve_path_fragment: E0424, source={:?}", source); - err.code(rustc_errors::error_code!(E0424)); + err.code(E0424); err.span_label( span, match source { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 925c3c0e27d68..9d09d060b59b8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -35,7 +35,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{FreezeReadGuard, Lrc}; -use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrCode}; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; @@ -256,7 +256,7 @@ enum ResolutionError<'a> { kind: &'static str, trait_path: String, trait_item_span: Span, - code: String, + code: ErrCode, }, /// Error E0201: multiple impl items for the same trait item. TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span }, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 1c085ddf57bf6..a6bf289a76a4c 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_code_err, Applicability}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability}; use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index e19f0fd84de56..c36cec6f35327 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -3,7 +3,7 @@ use std::num::NonZeroU32; use rustc_ast::token; use rustc_ast::util::literal::LitError; use rustc_errors::{ - error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, + codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, }; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -19,9 +19,7 @@ pub struct FeatureGateError { impl<'a> IntoDiagnostic<'a> for FeatureGateError { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { - DiagnosticBuilder::new(dcx, level, self.explain) - .with_span(self.span) - .with_code(error_code!(E0658)) + DiagnosticBuilder::new(dcx, level, self.explain).with_span(self.span).with_code(E0658) } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 891a83ce80cb8..7cd76ad729388 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -22,7 +22,7 @@ use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ - error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, + codes::*, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrCode, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl, }; use rustc_macros::HashStable_Generic; @@ -316,7 +316,7 @@ impl Session { ) -> DiagnosticBuilder<'a> { let mut err = self.dcx().create_err(err); if err.code.is_none() { - err.code(error_code!(E0658)); + err.code(E0658); } add_feature_diagnostics(&mut err, self, feature); err @@ -893,7 +893,7 @@ impl Session { CodegenUnits::Default(16) } - pub fn teach(&self, code: &str) -> bool { + pub fn teach(&self, code: ErrCode) -> bool { self.opts.unstable_opts.teach && self.dcx().must_teach(code) } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 5eff52afbca2b..7894f8dd98fff 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee, - IntoDiagnostic, Level, SubdiagnosticMessage, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessage, }; use rustc_macros::Diagnostic; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; @@ -25,7 +25,7 @@ pub struct UnableToConstructConstantValue<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")] +#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = E0232)] pub struct EmptyOnClauseInOnUnimplemented { #[primary_span] #[label] @@ -33,7 +33,7 @@ pub struct EmptyOnClauseInOnUnimplemented { } #[derive(Diagnostic)] -#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")] +#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = E0232)] pub struct InvalidOnClauseInOnUnimplemented { #[primary_span] #[label] @@ -41,7 +41,7 @@ pub struct InvalidOnClauseInOnUnimplemented { } #[derive(Diagnostic)] -#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = "E0232")] +#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = E0232)] #[note] pub struct NoValueInOnUnimplemented { #[primary_span] @@ -59,17 +59,13 @@ pub struct NegativePositiveConflict<'tcx> { impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] - fn into_diagnostic( - self, - dcx: &DiagCtxt, - level: Level, - ) -> rustc_errors::DiagnosticBuilder<'_, G> { + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::trait_selection_negative_positive_conflict); diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); diag.span(self.impl_span); - diag.code(rustc_errors::error_code!(E0751)); + diag.code(E0751); match self.negative_impl_span { Ok(span) => { diag.span_label(span, fluent::trait_selection_negative_implementation_here); @@ -132,7 +128,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow { } #[derive(Diagnostic)] -#[diag(trait_selection_closure_kind_mismatch, code = "E0525")] +#[diag(trait_selection_closure_kind_mismatch, code = E0525)] pub struct ClosureKindMismatch { #[primary_span] #[label] diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs index 864580afe623b..ca43436848bae 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs @@ -1,7 +1,7 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; use crate::traits::{Obligation, ObligationCause, ObligationCtxt}; -use rustc_errors::{pluralize, struct_span_code_err, Applicability, DiagnosticBuilder}; +use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::Node; use rustc_middle::ty::{self, Ty}; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index bb1b6ec139023..972da180a3365 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -6,7 +6,7 @@ use rustc_ast::AttrKind; use rustc_ast::{Attribute, MetaItem, NestedMetaItem}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_code_err, ErrorGuaranteed}; +use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::GenericArgsRef; 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 6a40ffebdada8..cdf99870006e7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -13,7 +13,7 @@ use hir::def::CtorOf; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - error_code, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, + codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan, Style, SuggestionStyle, }; use rustc_hir as hir; @@ -2014,7 +2014,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return false; }; - err.code(error_code!(E0746)); + err.code(E0746); err.primary_message("return type cannot have an unboxed trait object"); err.children.clear(); 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 149dcffe333de..2a09e95b2c55e 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 @@ -19,8 +19,8 @@ use crate::traits::{ }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{ - pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, - MultiSpan, StashKey, Style, + codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, MultiSpan, StashKey, Style, }; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; @@ -2529,7 +2529,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { corresponding `impl` type", ), ); - err.code(rustc_errors::error_code!(E0790)); + err.code(E0790); if let Some(local_def_id) = data.trait_ref.def_id.as_local() && let Some(hir::Node::Item(hir::Item { @@ -3162,7 +3162,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::ItemObligation(def_id) if self.tcx.is_fn_trait(*def_id) => { - err.code(rustc_errors::error_code!(E0059)); + err.code(E0059); err.primary_message(format!( "type parameter to bare `{}` trait must be a tuple", self.tcx.def_path_str(*def_id) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index bfc6937a3eb39..de08e7d2f0384 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -20,7 +20,7 @@ use crate::traits::{ self, coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt, }; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{error_code, DelayDm, Diagnostic}; +use rustc_errors::{codes::*, DelayDm, Diagnostic}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; @@ -449,7 +449,7 @@ fn report_conflicting_impls<'tcx>( || tcx.orphan_check_impl(impl_def_id).is_ok() { let mut err = tcx.dcx().struct_span_err(impl_span, msg); - err.code(error_code!(E0119)); + err.code(E0119); decorate(tcx, &overlap, impl_span, &mut err); err.emit() } else { diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index 947d4bbe86e1c..bfbb45f0cb501 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -1,5 +1,6 @@ //! Errors emitted by ty_utils +use rustc_errors::codes::*; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{GenericArg, Ty}; use rustc_span::Span; @@ -113,7 +114,7 @@ pub struct DuplicateArg<'tcx> { } #[derive(Diagnostic)] -#[diag(ty_utils_impl_trait_not_param, code = "E0792")] +#[diag(ty_utils_impl_trait_not_param, code = E0792)] pub struct NotParam<'tcx> { pub arg: GenericArg<'tcx>, #[primary_span] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8706abda97963..e1829da6e2c9a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -15,6 +15,7 @@ use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry}; +use rustc_errors::{codes::*, struct_span_code_err, FatalError}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; @@ -2271,7 +2272,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Placeholder(..) => panic!("Placeholder"), ty::CoroutineWitness(..) => panic!("CoroutineWitness"), ty::Infer(..) => panic!("Infer"), - ty::Error(_) => rustc_errors::FatalError.raise(), + ty::Error(_) => FatalError.raise(), } } @@ -2995,7 +2996,7 @@ fn clean_use_statement_inner<'tcx>( visibility.is_accessible_from(parent_mod, cx.tcx) && !current_mod.is_top_level_module(); if pub_underscore && let Some(ref inline) = inline_attr { - rustc_errors::struct_span_code_err!( + struct_span_code_err!( cx.tcx.dcx(), inline.span(), E0780, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 7cf385de6b77e..9eb62c258923f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -3,7 +3,7 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordSet; use rustc_errors::emitter::{DynEmitter, HumanEmitter}; use rustc_errors::json::JsonEmitter; -use rustc_errors::TerminalUrl; +use rustc_errors::{codes::*, TerminalUrl}; use rustc_feature::UnstableFeatures; use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId}; diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml index 76c2e330b2100..f4dac6e947e32 100644 --- a/src/tools/error_index_generator/Cargo.toml +++ b/src/tools/error_index_generator/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] mdbook = { version = "0.4", default-features = false, features = ["search"] } -rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" } [[bin]] name = "error_index_generator" diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 865d7172cd3e6..2de2d959a95d7 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -4,13 +4,15 @@ extern crate rustc_driver; extern crate rustc_log; extern crate rustc_session; +extern crate rustc_errors; +use rustc_errors::codes::DIAGNOSTICS; + use std::env; use std::error::Error; use std::fs::{self, File}; use std::io::Write; use std::path::Path; use std::path::PathBuf; - use std::str::FromStr; use mdbook::book::{parse_summary, BookItem, Chapter}; @@ -38,7 +40,7 @@ fn render_markdown(output_path: &Path) -> Result<(), Box> { write!(output_file, "# Rust Compiler Error Index\n")?; - for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() { + for (err_code, description) in DIAGNOSTICS.iter() { write!(output_file, "## {}\n{}\n", err_code, description)? } @@ -85,7 +87,7 @@ This page lists all the error codes emitted by the Rust compiler. " ); - let err_codes = rustc_error_codes::DIAGNOSTICS; + let err_codes = DIAGNOSTICS; let mut chapters = Vec::with_capacity(err_codes.len()); for (err_code, explanation) in err_codes.iter() { diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 094efa981d3e3..6fc65e56901a7 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -2,7 +2,7 @@ //! //! Overview of check: //! -//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/error_codes.rs`. +//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/lib.rs`. //! //! 2. We check that the error code has a long-form explanation in `compiler/rustc_error_codes/src/error_codes/`. //! - The explanation is expected to contain a `doctest` that fails with the correct error code. (`EXEMPT_FROM_DOCTEST` *currently* bypasses this check) @@ -22,7 +22,7 @@ use regex::Regex; use crate::walk::{filter_dirs, walk, walk_many}; -const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/error_codes.rs"; +const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/lib.rs"; const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/"; const ERROR_TESTS_PATH: &str = "tests/ui/error-codes/"; @@ -80,13 +80,14 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec) -> Vec) -> Vec, @@ -308,7 +312,7 @@ struct OptionsInErrors { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0456")] +#[diag(no_crate_example, code = E0123)] struct MoveOutOfBorrowError<'tcx> { name: Ident, ty: Ty<'tcx>, @@ -322,7 +326,7 @@ struct MoveOutOfBorrowError<'tcx> { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithLifetime<'a> { #[label(no_crate_label)] span: Span, @@ -330,7 +334,7 @@ struct ErrorWithLifetime<'a> { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithDefaultLabelAttr<'a> { #[label] span: Span, @@ -338,7 +342,7 @@ struct ErrorWithDefaultLabelAttr<'a> { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ArgFieldWithoutSkip { #[primary_span] span: Span, @@ -347,7 +351,7 @@ struct ArgFieldWithoutSkip { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ArgFieldWithSkip { #[primary_span] span: Span, @@ -358,56 +362,56 @@ struct ArgFieldWithSkip { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithSpannedNote { #[note] span: Span, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithSpannedNoteCustom { #[note(no_crate_note)] span: Span, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] #[note] struct ErrorWithNote { val: String, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] #[note(no_crate_note)] struct ErrorWithNoteCustom { val: String, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithSpannedHelp { #[help] span: Span, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithSpannedHelpCustom { #[help(no_crate_help)] span: Span, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] #[help] struct ErrorWithHelp { val: String, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] #[help(no_crate_help)] struct ErrorWithHelpCustom { val: String, @@ -415,34 +419,34 @@ struct ErrorWithHelpCustom { #[derive(Diagnostic)] #[help] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithHelpWrongOrder { val: String, } #[derive(Diagnostic)] #[help(no_crate_help)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithHelpCustomWrongOrder { val: String, } #[derive(Diagnostic)] #[note] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithNoteWrongOrder { val: String, } #[derive(Diagnostic)] #[note(no_crate_note)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithNoteCustomWrongOrder { val: String, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ApplicabilityInBoth { #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] //~^ ERROR specified multiple times @@ -450,7 +454,7 @@ struct ApplicabilityInBoth { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct InvalidApplicability { #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")] //~^ ERROR invalid applicability @@ -458,14 +462,14 @@ struct InvalidApplicability { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ValidApplicability { #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] suggestion: Span, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct NoApplicability { #[suggestion(no_crate_suggestion, code = "...")] suggestion: Span, @@ -483,7 +487,7 @@ struct Subdiagnostic { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct VecField { #[primary_span] #[label] @@ -491,7 +495,7 @@ struct VecField { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct UnitField { #[primary_span] spans: Span, @@ -502,7 +506,7 @@ struct UnitField { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct OptUnitField { #[primary_span] spans: Span, @@ -526,7 +530,7 @@ struct BoolField { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct LabelWithTrailingPath { #[label(no_crate_label, foo)] //~^ ERROR a diagnostic slug must be the first argument to the attribute @@ -534,7 +538,7 @@ struct LabelWithTrailingPath { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct LabelWithTrailingNameValue { #[label(no_crate_label, foo = "...")] //~^ ERROR only `no_span` is a valid nested attribute @@ -542,7 +546,7 @@ struct LabelWithTrailingNameValue { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct LabelWithTrailingList { #[label(no_crate_label, foo("..."))] //~^ ERROR only `no_span` is a valid nested attribute @@ -562,42 +566,42 @@ struct PrimarySpanOnLint { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct ErrorWithMultiSpan { #[primary_span] span: MultiSpan, } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] #[warning] struct ErrorWithWarn { val: String, } #[derive(Diagnostic)] -#[error(no_crate_example, code = "E0123")] +#[error(no_crate_example, code = E0123)] //~^ ERROR `#[error(...)]` is not a valid attribute //~| ERROR diagnostic slug not specified //~| ERROR cannot find attribute `error` in this scope struct ErrorAttribute {} #[derive(Diagnostic)] -#[warn_(no_crate_example, code = "E0123")] +#[warn_(no_crate_example, code = E0123)] //~^ ERROR `#[warn_(...)]` is not a valid attribute //~| ERROR diagnostic slug not specified //~| ERROR cannot find attribute `warn_` in this scope struct WarnAttribute {} #[derive(Diagnostic)] -#[lint(no_crate_example, code = "E0123")] +#[lint(no_crate_example, code = E0123)] //~^ ERROR `#[lint(...)]` is not a valid attribute //~| ERROR diagnostic slug not specified //~| ERROR cannot find attribute `lint` in this scope struct LintAttributeOnSessionDiag {} #[derive(LintDiagnostic)] -#[lint(no_crate_example, code = "E0123")] +#[lint(no_crate_example, code = E0123)] //~^ ERROR `#[lint(...)]` is not a valid attribute //~| ERROR `#[lint(...)]` is not a valid attribute //~| ERROR diagnostic slug not specified @@ -605,7 +609,7 @@ struct LintAttributeOnSessionDiag {} struct LintAttributeOnLintDiag {} #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct DuplicatedSuggestionCode { #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] //~^ ERROR specified multiple times @@ -613,7 +617,7 @@ struct DuplicatedSuggestionCode { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct InvalidTypeInSuggestionTuple { #[suggestion(no_crate_suggestion, code = "...")] suggestion: (Span, usize), @@ -621,7 +625,7 @@ struct InvalidTypeInSuggestionTuple { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct MissingApplicabilityInSuggestionTuple { #[suggestion(no_crate_suggestion, code = "...")] suggestion: (Span,), @@ -629,7 +633,7 @@ struct MissingApplicabilityInSuggestionTuple { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct MissingCodeInSuggestion { #[suggestion(no_crate_suggestion)] //~^ ERROR suggestion without `code = "..."` @@ -637,7 +641,7 @@ struct MissingCodeInSuggestion { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] #[multipart_suggestion(no_crate_suggestion)] //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute //~| ERROR cannot find attribute `multipart_suggestion` in this scope @@ -652,7 +656,7 @@ struct MultipartSuggestion { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] #[suggestion(no_crate_suggestion, code = "...")] //~^ ERROR `#[suggestion(...)]` is not a valid attribute struct SuggestionOnStruct { @@ -661,7 +665,7 @@ struct SuggestionOnStruct { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] #[label] //~^ ERROR `#[label]` is not a valid attribute struct LabelOnStruct { @@ -688,7 +692,7 @@ enum ExampleEnum { } #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct RawIdentDiagnosticArg { pub r#type: String, } @@ -762,7 +766,7 @@ struct SubdiagnosticEagerSuggestion { /// with a doc comment on the type.. #[derive(Diagnostic)] -#[diag(no_crate_example, code = "E0123")] +#[diag(no_crate_example, code = E0123)] struct WithDocComment { /// ..and the field #[primary_span] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index f376c034587fa..67257c28b6eb0 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -1,11 +1,11 @@ error: unsupported type attribute for diagnostic derive enum - --> $DIR/diagnostic-derive.rs:43:1 + --> $DIR/diagnostic-derive.rs:47:1 | -LL | #[diag(no_crate_example, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[diag(no_crate_example, code = E0123)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:46:5 + --> $DIR/diagnostic-derive.rs:50:5 | LL | Foo, | ^^^ @@ -13,7 +13,7 @@ LL | Foo, = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:48:5 + --> $DIR/diagnostic-derive.rs:52:5 | LL | Bar, | ^^^ @@ -21,15 +21,15 @@ LL | Bar, = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[nonsense(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:59:1 + --> $DIR/diagnostic-derive.rs:63:1 | -LL | #[nonsense(no_crate_example, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[nonsense(no_crate_example, code = E0123)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:59:1 + --> $DIR/diagnostic-derive.rs:63:1 | -LL | / #[nonsense(no_crate_example, code = "E0123")] +LL | / #[nonsense(no_crate_example, code = E0123)] LL | | LL | | LL | | @@ -39,9 +39,9 @@ LL | | struct InvalidStructAttr {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:66:1 + --> $DIR/diagnostic-derive.rs:70:1 | -LL | / #[diag("E0123")] +LL | / #[diag(code = E0123)] LL | | LL | | struct InvalidLitNestedAttr {} | |______________________________^ @@ -49,15 +49,15 @@ LL | | struct InvalidLitNestedAttr {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug must be the first argument - --> $DIR/diagnostic-derive.rs:76:16 + --> $DIR/diagnostic-derive.rs:80:16 | -LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")] +LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")] | ^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:76:1 + --> $DIR/diagnostic-derive.rs:80:1 | -LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")] +LL | / #[diag(nonsense("foo"), code = E0123, slug = "foo")] LL | | LL | | LL | | struct InvalidNestedStructAttr1 {} @@ -66,17 +66,17 @@ LL | | struct InvalidNestedStructAttr1 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: unknown argument - --> $DIR/diagnostic-derive.rs:82:8 + --> $DIR/diagnostic-derive.rs:86:8 | -LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] +LL | #[diag(nonsense = "...", code = E0123, slug = "foo")] | ^^^^^^^^ | = note: only the `code` parameter is valid after the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:82:1 + --> $DIR/diagnostic-derive.rs:86:1 | -LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")] +LL | / #[diag(nonsense = "...", code = E0123, slug = "foo")] LL | | LL | | LL | | struct InvalidNestedStructAttr2 {} @@ -85,17 +85,17 @@ LL | | struct InvalidNestedStructAttr2 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: unknown argument - --> $DIR/diagnostic-derive.rs:88:8 + --> $DIR/diagnostic-derive.rs:92:8 | -LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] +LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] | ^^^^^^^^ | = note: only the `code` parameter is valid after the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:88:1 + --> $DIR/diagnostic-derive.rs:92:1 | -LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")] +LL | / #[diag(nonsense = 4, code = E0123, slug = "foo")] LL | | LL | | LL | | struct InvalidNestedStructAttr3 {} @@ -104,63 +104,63 @@ LL | | struct InvalidNestedStructAttr3 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: unknown argument - --> $DIR/diagnostic-derive.rs:94:42 + --> $DIR/diagnostic-derive.rs:98:40 | -LL | #[diag(no_crate_example, code = "E0123", slug = "foo")] - | ^^^^ +LL | #[diag(no_crate_example, code = E0123, slug = "foo")] + | ^^^^ | = note: only the `code` parameter is valid after the slug error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:101:5 + --> $DIR/diagnostic-derive.rs:105:5 | LL | #[suggestion = "bar"] | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:108:8 + --> $DIR/diagnostic-derive.rs:112:8 | -LL | #[diag(no_crate_example, code = "E0456")] +LL | #[diag(no_crate_example, code = E0456)] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:107:8 + --> $DIR/diagnostic-derive.rs:111:8 | -LL | #[diag(no_crate_example, code = "E0123")] +LL | #[diag(no_crate_example, code = E0123)] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:108:26 + --> $DIR/diagnostic-derive.rs:112:26 | -LL | #[diag(no_crate_example, code = "E0456")] +LL | #[diag(no_crate_example, code = E0456)] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:107:26 + --> $DIR/diagnostic-derive.rs:111:26 | -LL | #[diag(no_crate_example, code = "E0123")] +LL | #[diag(no_crate_example, code = E0123)] | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:114:42 + --> $DIR/diagnostic-derive.rs:118:40 | -LL | #[diag(no_crate_example, code = "E0456", code = "E0457")] - | ^^^^ +LL | #[diag(no_crate_example, code = E0123, code = E0456)] + | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:114:26 + --> $DIR/diagnostic-derive.rs:118:26 | -LL | #[diag(no_crate_example, code = "E0456", code = "E0457")] +LL | #[diag(no_crate_example, code = E0123, code = E0456)] | ^^^^ error: diagnostic slug must be the first argument - --> $DIR/diagnostic-derive.rs:119:43 + --> $DIR/diagnostic-derive.rs:123:43 | -LL | #[diag(no_crate_example, no_crate::example, code = "E0456")] +LL | #[diag(no_crate_example, no_crate::example, code = E0123)] | ^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:124:1 + --> $DIR/diagnostic-derive.rs:128:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -168,9 +168,9 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:127:1 + --> $DIR/diagnostic-derive.rs:131:1 | -LL | / #[diag(code = "E0456")] +LL | / #[diag(code = E0123)] LL | | LL | | struct SlugNotProvided {} | |_________________________^ @@ -178,31 +178,31 @@ LL | | struct SlugNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:138:5 + --> $DIR/diagnostic-derive.rs:142:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:146:5 + --> $DIR/diagnostic-derive.rs:150:5 | LL | #[nonsense] | ^^^^^^^^^^^ error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:163:5 + --> $DIR/diagnostic-derive.rs:167:5 | LL | #[label(no_crate_label)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:171:46 + --> $DIR/diagnostic-derive.rs:175:46 | LL | #[suggestion(no_crate_suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:176:10 + --> $DIR/diagnostic-derive.rs:180:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ expected `'}'` in format string @@ -211,7 +211,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:186:10 + --> $DIR/diagnostic-derive.rs:190:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ unmatched `}` in format string @@ -220,19 +220,19 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:206:5 + --> $DIR/diagnostic-derive.rs:210:5 | LL | #[label(no_crate_label)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:225:5 + --> $DIR/diagnostic-derive.rs:229:5 | LL | #[suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid nested attribute - --> $DIR/diagnostic-derive.rs:233:18 + --> $DIR/diagnostic-derive.rs:237:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^ @@ -240,13 +240,13 @@ LL | #[suggestion(nonsense = "bar")] = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:233:5 + --> $DIR/diagnostic-derive.rs:237:5 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid nested attribute - --> $DIR/diagnostic-derive.rs:242:18 + --> $DIR/diagnostic-derive.rs:246:18 | LL | #[suggestion(msg = "bar")] | ^^^ @@ -254,13 +254,13 @@ LL | #[suggestion(msg = "bar")] = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:242:5 + --> $DIR/diagnostic-derive.rs:246:5 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:265:5 + --> $DIR/diagnostic-derive.rs:269:5 | LL | / #[suggestion(no_crate_suggestion, code = "This is suggested code")] LL | | @@ -270,79 +270,79 @@ LL | | suggestion: Applicability, = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: specified multiple times - --> $DIR/diagnostic-derive.rs:281:24 + --> $DIR/diagnostic-derive.rs:285:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:281:18 + --> $DIR/diagnostic-derive.rs:285:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:289:33 + --> $DIR/diagnostic-derive.rs:293:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:289:18 + --> $DIR/diagnostic-derive.rs:293:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:296:5 + --> $DIR/diagnostic-derive.rs:300:5 | LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:447:5 + --> $DIR/diagnostic-derive.rs:451:5 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:449:24 + --> $DIR/diagnostic-derive.rs:453:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:455:69 + --> $DIR/diagnostic-derive.rs:459:69 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")] | ^^^^^^^^ error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()` - --> $DIR/diagnostic-derive.rs:522:5 + --> $DIR/diagnostic-derive.rs:526:5 | LL | #[help(no_crate_help)] | ^^^^^^^^^^^^^^^^^^^^^^ error: a diagnostic slug must be the first argument to the attribute - --> $DIR/diagnostic-derive.rs:531:32 + --> $DIR/diagnostic-derive.rs:535:32 | LL | #[label(no_crate_label, foo)] | ^ error: only `no_span` is a valid nested attribute - --> $DIR/diagnostic-derive.rs:539:29 + --> $DIR/diagnostic-derive.rs:543:29 | LL | #[label(no_crate_label, foo = "...")] | ^^^ error: only `no_span` is a valid nested attribute - --> $DIR/diagnostic-derive.rs:547:29 + --> $DIR/diagnostic-derive.rs:551:29 | LL | #[label(no_crate_label, foo("..."))] | ^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:559:5 + --> $DIR/diagnostic-derive.rs:563:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -350,15 +350,15 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:579:1 + --> $DIR/diagnostic-derive.rs:583:1 | -LL | #[error(no_crate_example, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(no_crate_example, code = E0123)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:579:1 + --> $DIR/diagnostic-derive.rs:583:1 | -LL | / #[error(no_crate_example, code = "E0123")] +LL | / #[error(no_crate_example, code = E0123)] LL | | LL | | LL | | @@ -368,15 +368,15 @@ LL | | struct ErrorAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:586:1 + --> $DIR/diagnostic-derive.rs:590:1 | -LL | #[warn_(no_crate_example, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[warn_(no_crate_example, code = E0123)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:586:1 + --> $DIR/diagnostic-derive.rs:590:1 | -LL | / #[warn_(no_crate_example, code = "E0123")] +LL | / #[warn_(no_crate_example, code = E0123)] LL | | LL | | LL | | @@ -386,15 +386,15 @@ LL | | struct WarnAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:593:1 + --> $DIR/diagnostic-derive.rs:597:1 | -LL | #[lint(no_crate_example, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[lint(no_crate_example, code = E0123)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:593:1 + --> $DIR/diagnostic-derive.rs:597:1 | -LL | / #[lint(no_crate_example, code = "E0123")] +LL | / #[lint(no_crate_example, code = E0123)] LL | | LL | | LL | | @@ -404,23 +404,23 @@ LL | | struct LintAttributeOnSessionDiag {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:600:1 + --> $DIR/diagnostic-derive.rs:604:1 | -LL | #[lint(no_crate_example, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[lint(no_crate_example, code = E0123)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:600:1 + --> $DIR/diagnostic-derive.rs:604:1 | -LL | #[lint(no_crate_example, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[lint(no_crate_example, code = E0123)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:600:1 + --> $DIR/diagnostic-derive.rs:604:1 | -LL | / #[lint(no_crate_example, code = "E0123")] +LL | / #[lint(no_crate_example, code = E0123)] LL | | LL | | LL | | @@ -431,19 +431,19 @@ LL | | struct LintAttributeOnLintDiag {} = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]` error: specified multiple times - --> $DIR/diagnostic-derive.rs:610:53 + --> $DIR/diagnostic-derive.rs:614:53 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:610:39 + --> $DIR/diagnostic-derive.rs:614:39 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] | ^^^^ error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:619:24 + --> $DIR/diagnostic-derive.rs:623:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -451,7 +451,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:627:17 + --> $DIR/diagnostic-derive.rs:631:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -459,13 +459,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:634:5 + --> $DIR/diagnostic-derive.rs:638:5 | LL | #[suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:641:1 + --> $DIR/diagnostic-derive.rs:645:1 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -473,7 +473,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)] = help: consider creating a `Subdiagnostic` instead error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:644:1 + --> $DIR/diagnostic-derive.rs:648:1 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -481,7 +481,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:648:5 + --> $DIR/diagnostic-derive.rs:652:5 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -489,7 +489,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)] = help: consider creating a `Subdiagnostic` instead error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:656:1 + --> $DIR/diagnostic-derive.rs:660:1 | LL | #[suggestion(no_crate_suggestion, code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL | #[suggestion(no_crate_suggestion, code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:665:1 + --> $DIR/diagnostic-derive.rs:669:1 | LL | #[label] | ^^^^^^^^ @@ -505,31 +505,31 @@ LL | #[label] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:699:7 + --> $DIR/diagnostic-derive.rs:703:7 | LL | #[subdiagnostic(bad)] | ^^^^^^^^^^^^^^^^^^ error: `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:707:5 + --> $DIR/diagnostic-derive.rs:711:5 | LL | #[subdiagnostic = "bad"] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:715:7 + --> $DIR/diagnostic-derive.rs:719:7 | LL | #[subdiagnostic(bad, bad)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:723:7 + --> $DIR/diagnostic-derive.rs:727:7 | LL | #[subdiagnostic("bad")] | ^^^^^^^^^^^^^^^^^^^^ error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:731:5 + --> $DIR/diagnostic-derive.rs:735:5 | LL | #[subdiagnostic(eager)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -537,19 +537,19 @@ LL | #[subdiagnostic(eager)] = help: eager subdiagnostics are not supported on lints error: expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive.rs:789:23 + --> $DIR/diagnostic-derive.rs:793:23 | LL | #[suggestion(code())] | ^ error: `code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:797:23 + --> $DIR/diagnostic-derive.rs:801:23 | LL | #[suggestion(code(foo))] | ^^^ error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:821:5 + --> $DIR/diagnostic-derive.rs:825:5 | LL | #[suggestion(no_crate_suggestion, code = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -559,85 +559,85 @@ LL | #[suggestion(no_crate_suggestion, code = "")] = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:54:8 + --> $DIR/diagnostic-derive.rs:58:8 | LL | #[diag = "E0123"] | ^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:797:23 + --> $DIR/diagnostic-derive.rs:801:23 | LL | #[suggestion(code(foo))] | ^^^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:806:25 + --> $DIR/diagnostic-derive.rs:810:25 | LL | #[suggestion(code = 3)] | ^ maybe a missing crate `core`? error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:59:3 + --> $DIR/diagnostic-derive.rs:63:3 | -LL | #[nonsense(no_crate_example, code = "E0123")] +LL | #[nonsense(no_crate_example, code = E0123)] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:146:7 + --> $DIR/diagnostic-derive.rs:150:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:579:3 + --> $DIR/diagnostic-derive.rs:583:3 | -LL | #[error(no_crate_example, code = "E0123")] +LL | #[error(no_crate_example, code = E0123)] | ^^^^^ error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:586:3 + --> $DIR/diagnostic-derive.rs:590:3 | -LL | #[warn_(no_crate_example, code = "E0123")] +LL | #[warn_(no_crate_example, code = E0123)] | ^^^^^ help: a built-in attribute with a similar name exists: `warn` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:593:3 + --> $DIR/diagnostic-derive.rs:597:3 | -LL | #[lint(no_crate_example, code = "E0123")] +LL | #[lint(no_crate_example, code = E0123)] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:600:3 + --> $DIR/diagnostic-derive.rs:604:3 | -LL | #[lint(no_crate_example, code = "E0123")] +LL | #[lint(no_crate_example, code = E0123)] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:641:3 + --> $DIR/diagnostic-derive.rs:645:3 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:644:3 + --> $DIR/diagnostic-derive.rs:648:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:648:7 + --> $DIR/diagnostic-derive.rs:652:7 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated` - --> $DIR/diagnostic-derive.rs:71:8 + --> $DIR/diagnostic-derive.rs:75:8 | -LL | #[diag(nonsense, code = "E0123")] +LL | #[diag(nonsense, code = E0123)] | ^^^^^^^^ not found in `crate::fluent_generated` error[E0425]: cannot find value `__code_34` in this scope - --> $DIR/diagnostic-derive.rs:803:10 + --> $DIR/diagnostic-derive.rs:807:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ not found in this scope @@ -645,7 +645,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:345:12 + --> $DIR/diagnostic-derive.rs:349:12 | LL | #[derive(Diagnostic)] | ---------- required by a bound introduced by this call diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs index a0a8114e0c5c5..785da11b9b2e3 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 = "E0123")] +#[diag(compiletest_example, code = 0123)] //~^ 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 4cdc24e6a6bc9..eda24a555f848 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 = "E0123")] +LL | #[diag(compiletest_example, code = 0123)] | ^^^^^^^^^^^^^^^^^^^ | = note: slug is `compiletest_example` but the crate name is `rustc_dummy` diff --git a/triagebot.toml b/triagebot.toml index c46f9c9003079..e57dd158374f8 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -476,7 +476,7 @@ of `ObligationCtxt`. """ cc = ["@lcnr", "@compiler-errors"] -[mentions."compiler/rustc_error_codes/src/error_codes.rs"] +[mentions."compiler/rustc_error_codes/src/lib.rs"] message = "Some changes occurred in diagnostic error codes" cc = ["@GuillaumeGomez"] From 6aec11afbcf3acd195818948a3e7a8d5b337b78a Mon Sep 17 00:00:00 2001 From: Ryan Lowe Date: Sun, 28 Jan 2024 13:27:17 -0500 Subject: [PATCH 333/676] 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 103159809aa83e00111f3b35be7281b8165681bc Mon Sep 17 00:00:00 2001 From: Jarl Evanson Date: Sun, 28 Jan 2024 16:04:07 -0600 Subject: [PATCH 334/676] Enable `lifetimes` SROA MIR-opt test --- tests/mir-opt/sroa/lifetimes.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/sroa/lifetimes.rs b/tests/mir-opt/sroa/lifetimes.rs index cc5c0c9bbcdb5..ea04fac15710e 100644 --- a/tests/mir-opt/sroa/lifetimes.rs +++ b/tests/mir-opt/sroa/lifetimes.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ScalarReplacementOfAggregates // compile-flags: -Cpanic=abort // no-prefer-dynamic @@ -16,6 +15,10 @@ struct Foo { // EMIT_MIR lifetimes.foo.ScalarReplacementOfAggregates.diff fn foo() { + // CHECK-LABEL: fn foo( + + // CHECK-NOT: [foo:_.*]: Foo + // CHECK-NOT: Box let foo: Foo = Foo { x: Ok(Box::new(5_u32)), y: 7_u32, From 5bda589ff333dc324963bc653ce9e13bb176e6a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 29 Jan 2024 09:28:10 +1100 Subject: [PATCH 335/676] Tweak comment and naming for `recover_unclosed_char`. Because it can be used for a lifetime or a label. --- compiler/rustc_parse/src/parser/expr.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b789b65797bad..ad26a930829e1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1737,16 +1737,16 @@ impl<'a> Parser<'a> { Ok(expr) } - /// Emit an error when a char is parsed as a lifetime because of a missing quote. + /// Emit an error when a char is parsed as a lifetime or label because of a missing quote. pub(super) fn recover_unclosed_char( &self, - lifetime: Ident, + ident: Ident, mk_lit_char: impl FnOnce(Symbol, Span) -> L, err: impl FnOnce(&Self) -> DiagnosticBuilder<'a>, ) -> L { - if let Some(diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) { + if let Some(diag) = self.dcx().steal_diagnostic(ident.span, StashKey::LifetimeIsChar) { diag.with_span_suggestion_verbose( - lifetime.span.shrink_to_hi(), + ident.span.shrink_to_hi(), "add `'` to close the char literal", "'", Applicability::MaybeIncorrect, @@ -1755,15 +1755,15 @@ impl<'a> Parser<'a> { } else { err(self) .with_span_suggestion_verbose( - lifetime.span.shrink_to_hi(), + ident.span.shrink_to_hi(), "add `'` to close the char literal", "'", Applicability::MaybeIncorrect, ) .emit(); } - let name = lifetime.without_first_quote().name; - mk_lit_char(name, lifetime.span) + let name = ident.without_first_quote().name; + mk_lit_char(name, ident.span) } /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. From 306612ea60850249e0ad9e7a14fb1ce75fcd944e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 29 Jan 2024 09:47:02 +1100 Subject: [PATCH 336/676] Be more careful about interpreting a label/lifetime as a mistyped char literal. Currently the parser will interpret any label/lifetime in certain positions as a mistyped char literal, on the assumption that the trailing single quote was accidentally omitted. This is reasonable for a something like 'a (because 'a' would be valid) but not reasonable for a something like 'abc (because 'abc' is not valid). This commit restricts this behaviour only to labels/lifetimes that would be valid char literals, via the new `could_be_unclosed_char_literal` function. The commit also augments the `label-is-actually-char.rs` test in a couple of ways: - Adds testing of labels/lifetimes with identifiers longer than one char, e.g. 'abc. - Adds a new match with simpler patterns, because the `recover_unclosed_char` call in `parse_pat_with_range_pat` was not being exercised (in this test or any other ui tests). Fixes #120397, an assertion failure, which was caused by this behaviour in the parser interacting with some new stricter char literal checking added in #120329. --- compiler/rustc_parse/src/parser/expr.rs | 17 ++++- compiler/rustc_parse/src/parser/pat.rs | 4 +- tests/ui/parser/label-is-actually-char.rs | 41 +++++++++-- tests/ui/parser/label-is-actually-char.stderr | 73 +++++++++++++++---- 4 files changed, 112 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ad26a930829e1..583f6f2ae5f4b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -28,6 +28,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, PResult, StashKey, }; +use rustc_lexer::unescape::unescape_char; use rustc_macros::Subdiagnostic; use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; @@ -1652,6 +1653,7 @@ impl<'a> Parser<'a> { && self.may_recover() && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma) || self.token.is_punct()) + && could_be_unclosed_char_literal(label_.ident) { let (lit, _) = self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| { @@ -1744,6 +1746,7 @@ impl<'a> Parser<'a> { mk_lit_char: impl FnOnce(Symbol, Span) -> L, err: impl FnOnce(&Self) -> DiagnosticBuilder<'a>, ) -> L { + assert!(could_be_unclosed_char_literal(ident)); if let Some(diag) = self.dcx().steal_diagnostic(ident.span, StashKey::LifetimeIsChar) { diag.with_span_suggestion_verbose( ident.span.shrink_to_hi(), @@ -2034,8 +2037,11 @@ impl<'a> Parser<'a> { let msg = format!("unexpected token: {}", super::token_descr(&token)); self_.dcx().struct_span_err(token.span, msg) }; - // On an error path, eagerly consider a lifetime to be an unclosed character lit - if self.token.is_lifetime() { + // On an error path, eagerly consider a lifetime to be an unclosed character lit, if that + // makes sense. + if let Some(ident) = self.token.lifetime() + && could_be_unclosed_char_literal(ident) + { let lt = self.expect_lifetime(); Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err)) } else { @@ -3763,6 +3769,13 @@ impl<'a> Parser<'a> { } } +/// Could this lifetime/label be an unclosed char literal? For example, `'a` +/// could be, but `'abc` could not. +pub(crate) fn could_be_unclosed_char_literal(ident: Ident) -> bool { + ident.name.as_str().starts_with('\'') + && unescape_char(ident.without_first_quote().name.as_str()).is_ok() +} + /// Used to forbid `let` expressions in certain syntactic locations. #[derive(Clone, Copy, Subdiagnostic)] pub(crate) enum ForbiddenLetReason { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 7918e03750ce3..55144c6165012 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -10,6 +10,7 @@ use crate::errors::{ UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, }; +use crate::parser::expr::could_be_unclosed_char_literal; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; @@ -443,11 +444,12 @@ impl<'a> Parser<'a> { } else { PatKind::Path(qself, path) } - } else if matches!(self.token.kind, token::Lifetime(_)) + } else if let token::Lifetime(lt) = self.token.kind // In pattern position, we're totally fine with using "next token isn't colon" // as a heuristic. We could probably just always try to recover if it's a lifetime, // because we never have `'a: label {}` in a pattern position anyways, but it does // keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..` + && could_be_unclosed_char_literal(Ident::with_dummy_span(lt)) && !self.look_ahead(1, |token| matches!(token.kind, token::Colon)) { // Recover a `'a` as a `'a'` literal diff --git a/tests/ui/parser/label-is-actually-char.rs b/tests/ui/parser/label-is-actually-char.rs index 183da603da434..74df898d1910a 100644 --- a/tests/ui/parser/label-is-actually-char.rs +++ b/tests/ui/parser/label-is-actually-char.rs @@ -1,16 +1,43 @@ +// Note: it's ok to interpret 'a as 'a', but but not ok to interpret 'abc as +// 'abc' because 'abc' is not a valid char literal. + fn main() { let c = 'a; //~^ ERROR expected `while`, `for`, `loop` or `{` after a label //~| HELP add `'` to close the char literal - match c { + + let c = 'abc; + //~^ ERROR expected `while`, `for`, `loop` or `{` after a label + //~| ERROR expected expression, found `;` +} + +fn f() { + match 'a' { 'a'..='b => {} //~^ ERROR unexpected token: `'b` //~| HELP add `'` to close the char literal - _ => {} + 'c'..='def => {} + //~^ ERROR unexpected token: `'def` } - let x = ['a, 'b]; - //~^ ERROR expected `while`, `for`, `loop` or `{` after a label - //~| ERROR expected `while`, `for`, `loop` or `{` after a label - //~| HELP add `'` to close the char literal - //~| HELP add `'` to close the char literal +} + +fn g() { + match 'g' { + 'g => {} + //~^ ERROR expected pattern, found `=>` + //~| HELP add `'` to close the char literal + 'hij => {} + //~^ ERROR expected pattern, found `'hij` + _ => {} + } +} + +fn h() { + let x = ['a, 'b, 'cde]; + //~^ ERROR expected `while`, `for`, `loop` or `{` after a label + //~| HELP add `'` to close the char literal + //~| ERROR expected `while`, `for`, `loop` or `{` after a label + //~| HELP add `'` to close the char literal + //~| ERROR expected `while`, `for`, `loop` or `{` after a label + //~| ERROR expected expression, found `]` } diff --git a/tests/ui/parser/label-is-actually-char.stderr b/tests/ui/parser/label-is-actually-char.stderr index 28c8d2ada3adb..10a7e1803b532 100644 --- a/tests/ui/parser/label-is-actually-char.stderr +++ b/tests/ui/parser/label-is-actually-char.stderr @@ -1,5 +1,5 @@ error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/label-is-actually-char.rs:2:15 + --> $DIR/label-is-actually-char.rs:5:15 | LL | let c = 'a; | ^ expected `while`, `for`, `loop` or `{` after a label @@ -9,8 +9,20 @@ help: add `'` to close the char literal LL | let c = 'a'; | + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/label-is-actually-char.rs:9:17 + | +LL | let c = 'abc; + | ^ expected `while`, `for`, `loop` or `{` after a label + +error: expected expression, found `;` + --> $DIR/label-is-actually-char.rs:9:17 + | +LL | let c = 'abc; + | ^ expected expression + error: unexpected token: `'b` - --> $DIR/label-is-actually-char.rs:6:15 + --> $DIR/label-is-actually-char.rs:16:15 | LL | 'a'..='b => {} | ^^ @@ -20,27 +32,62 @@ help: add `'` to close the char literal LL | 'a'..='b' => {} | + +error: unexpected token: `'def` + --> $DIR/label-is-actually-char.rs:19:15 + | +LL | 'c'..='def => {} + | ^^^^ + +error: expected pattern, found `=>` + --> $DIR/label-is-actually-char.rs:26:11 + | +LL | 'g => {} + | ^^ expected pattern + | +help: add `'` to close the char literal + | +LL | 'g' => {} + | + + +error: expected pattern, found `'hij` + --> $DIR/label-is-actually-char.rs:29:8 + | +LL | 'hij => {} + | ^^^^ expected pattern + error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/label-is-actually-char.rs:11:16 + --> $DIR/label-is-actually-char.rs:36:15 | -LL | let x = ['a, 'b]; - | ^ expected `while`, `for`, `loop` or `{` after a label +LL | let x = ['a, 'b, 'cde]; + | ^ expected `while`, `for`, `loop` or `{` after a label | help: add `'` to close the char literal | -LL | let x = ['a', 'b]; - | + +LL | let x = ['a', 'b, 'cde]; + | + error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/label-is-actually-char.rs:11:20 + --> $DIR/label-is-actually-char.rs:36:19 | -LL | let x = ['a, 'b]; - | ^ expected `while`, `for`, `loop` or `{` after a label +LL | let x = ['a, 'b, 'cde]; + | ^ expected `while`, `for`, `loop` or `{` after a label | help: add `'` to close the char literal | -LL | let x = ['a, 'b']; - | + +LL | let x = ['a, 'b', 'cde]; + | + + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/label-is-actually-char.rs:36:25 + | +LL | let x = ['a, 'b, 'cde]; + | ^ expected `while`, `for`, `loop` or `{` after a label + +error: expected expression, found `]` + --> $DIR/label-is-actually-char.rs:36:25 + | +LL | let x = ['a, 'b, 'cde]; + | ^ expected expression -error: aborting due to 4 previous errors +error: aborting due to 11 previous errors From 3cde0e8fb603f696e895fb4cb817fcd44df827f8 Mon Sep 17 00:00:00 2001 From: Marek 'seqre' Grzelak Date: Fri, 26 Jan 2024 18:41:45 -0600 Subject: [PATCH 337/676] Add instructions of how to use pre-vendored 'rustc-src' --- src/bootstrap/bootstrap.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 83fdcddecf27a..0d604c0d3e5e0 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1034,7 +1034,16 @@ def check_vendored_status(self): eprint('ERROR: vendoring required, but vendor directory does not exist.') eprint(' Run `cargo vendor {}` to initialize the ' 'vendor directory.'.format(sync_dirs)) - eprint('Alternatively, use the pre-vendored `rustc-src` dist component.') + eprint(' Alternatively, use the pre-vendored `rustc-src` dist component.') + eprint(' To get a stable/beta/nightly version, download it from: ') + eprint(' ' + 'https://forge.rust-lang.org/infra/other-installation-methods.html#source-code') + eprint(' To get a specific commit version, download it using the below URL,') + eprint(' replacing with a specific commit checksum: ') + eprint(' ' + 'https://ci-artifacts.rust-lang.org/rustc-builds//rustc-nightly-src.tar.xz') + eprint(' Once you have the source downloaded, place the vendor directory') + eprint(' from the archive in the root of the rust project.') raise Exception("{} not found".format(vendor_dir)) if not os.path.exists(cargo_dir): From d3bf8b717b81a57fcf8d6196743a8359f7d50800 Mon Sep 17 00:00:00 2001 From: r0cky Date: Sun, 28 Jan 2024 22:03:33 +0800 Subject: [PATCH 338/676] Clean dead code --- library/std/src/sys/pal/wasi/net.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/std/src/sys/pal/wasi/net.rs b/library/std/src/sys/pal/wasi/net.rs index 2239880ffbef4..2098d05db0bc7 100644 --- a/library/std/src/sys/pal/wasi/net.rs +++ b/library/std/src/sys/pal/wasi/net.rs @@ -538,7 +538,4 @@ pub mod netc { pub sin6_flowinfo: u32, pub sin6_scope_id: u32, } - - #[derive(Copy, Clone)] - pub struct sockaddr {} } From 699b59c01d1b3e67b5a29646705d9824e03ff1ad Mon Sep 17 00:00:00 2001 From: sfzhu93 Date: Sun, 28 Jan 2024 22:44:32 -0800 Subject: [PATCH 339/676] 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 b4e1c569fe1d332fae69a1c04139116adfbf1a7c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jan 2024 14:08:29 +0100 Subject: [PATCH 340/676] raw pointer metadata API: data address -> data pointer --- library/core/src/ptr/const_ptr.rs | 2 +- library/core/src/ptr/metadata.rs | 16 ++++++++-------- library/core/src/ptr/mut_ptr.rs | 2 +- library/core/src/ptr/non_null.rs | 8 ++++---- ...ed_mut_range.PreCodegen.after.panic-abort.mir | 4 ++-- ...d_mut_range.PreCodegen.after.panic-unwind.mir | 4 ++-- tests/ui/union/issue-81199.rs | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 5ce9ddeb676a6..f3ceadee24c2f 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -285,7 +285,7 @@ impl *const T { self.with_addr(f(self.addr())) } - /// Decompose a (possibly wide) pointer into its address and metadata components. + /// Decompose a (possibly wide) pointer into its data pointer and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts`]. #[unstable(feature = "ptr_metadata", issue = "81513")] diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 040aa06978748..a6a390db043b6 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -39,13 +39,13 @@ use crate::hash::{Hash, Hasher}; /// /// # Usage /// -/// Raw pointers can be decomposed into the data address and metadata components +/// Raw pointers can be decomposed into the data pointer and metadata components /// with their [`to_raw_parts`] method. /// /// Alternatively, metadata alone can be extracted with the [`metadata`] function. /// A reference can be passed to [`metadata`] and implicitly coerced. /// -/// A (possibly-wide) pointer can be put back together from its address and metadata +/// A (possibly-wide) pointer can be put back together from its data pointer and metadata /// with [`from_raw_parts`] or [`from_raw_parts_mut`]. /// /// [`to_raw_parts`]: *const::to_raw_parts @@ -98,7 +98,7 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { unsafe { PtrRepr { const_ptr: ptr }.components.metadata } } -/// Forms a (possibly-wide) raw pointer from a data address and metadata. +/// Forms a (possibly-wide) raw pointer from a data pointer and metadata. /// /// This function is safe but the returned pointer is not necessarily safe to dereference. /// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements. @@ -109,13 +109,13 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] pub const fn from_raw_parts( - data_address: *const (), + data_pointer: *const (), metadata: ::Metadata, ) -> *const T { // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T // and PtrComponents have the same memory layouts. Only std can make this // guarantee. - unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.const_ptr } + unsafe { PtrRepr { components: PtrComponents { data_pointer, metadata } }.const_ptr } } /// Performs the same functionality as [`from_raw_parts`], except that a @@ -126,13 +126,13 @@ pub const fn from_raw_parts( #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] pub const fn from_raw_parts_mut( - data_address: *mut (), + data_pointer: *mut (), metadata: ::Metadata, ) -> *mut T { // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T // and PtrComponents have the same memory layouts. Only std can make this // guarantee. - unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.mut_ptr } + unsafe { PtrRepr { components: PtrComponents { data_pointer, metadata } }.mut_ptr } } #[repr(C)] @@ -144,7 +144,7 @@ union PtrRepr { #[repr(C)] struct PtrComponents { - data_address: *const (), + data_pointer: *const (), metadata: ::Metadata, } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 3e5678a7d9172..3e47c4f440a44 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -292,7 +292,7 @@ impl *mut T { self.with_addr(f(self.addr())) } - /// Decompose a (possibly wide) pointer into its address and metadata components. + /// Decompose a (possibly wide) pointer into its data pointer and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts_mut`]. #[unstable(feature = "ptr_metadata", issue = "81513")] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 427a9f3f49456..d18082c3048f1 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -259,16 +259,16 @@ impl NonNull { #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] pub const fn from_raw_parts( - data_address: NonNull<()>, + data_pointer: NonNull<()>, metadata: ::Metadata, ) -> NonNull { - // SAFETY: The result of `ptr::from::raw_parts_mut` is non-null because `data_address` is. + // SAFETY: The result of `ptr::from::raw_parts_mut` is non-null because `data_pointer` is. unsafe { - NonNull::new_unchecked(super::from_raw_parts_mut(data_address.as_ptr(), metadata)) + NonNull::new_unchecked(super::from_raw_parts_mut(data_pointer.as_ptr(), metadata)) } } - /// Decompose a (possibly wide) pointer into its address and metadata components. + /// Decompose a (possibly wide) pointer into its data pointer and metadata components. /// /// The pointer can be later reconstructed with [`NonNull::from_raw_parts`]. #[unstable(feature = "ptr_metadata", issue = "81513")] diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index 36329f8fc6845..dc37c1b4cbf9f 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -42,7 +42,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug self => _8; } scope 15 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { - debug data_address => _9; + debug data_pointer => _9; debug metadata => _6; let mut _10: *const (); let mut _11: std::ptr::metadata::PtrComponents<[u32]>; @@ -90,7 +90,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_11); StorageLive(_10); _10 = _9 as *const () (PointerCoercion(MutToConstPointer)); - _11 = std::ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 }; + _11 = std::ptr::metadata::PtrComponents::<[u32]> { data_pointer: move _10, metadata: _6 }; StorageDead(_10); _12 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 }; StorageDead(_11); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 36329f8fc6845..dc37c1b4cbf9f 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -42,7 +42,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug self => _8; } scope 15 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { - debug data_address => _9; + debug data_pointer => _9; debug metadata => _6; let mut _10: *const (); let mut _11: std::ptr::metadata::PtrComponents<[u32]>; @@ -90,7 +90,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_11); StorageLive(_10); _10 = _9 as *const () (PointerCoercion(MutToConstPointer)); - _11 = std::ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 }; + _11 = std::ptr::metadata::PtrComponents::<[u32]> { data_pointer: move _10, metadata: _6 }; StorageDead(_10); _12 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 }; StorageDead(_11); diff --git a/tests/ui/union/issue-81199.rs b/tests/ui/union/issue-81199.rs index b8b0d9d33e791..2083ee15d87bd 100644 --- a/tests/ui/union/issue-81199.rs +++ b/tests/ui/union/issue-81199.rs @@ -9,7 +9,7 @@ union PtrRepr { #[repr(C)] struct PtrComponents { - data_address: *const (), + data_pointer: *const (), metadata: ::Metadata, } From 7a2b66319ee219e757b6661549f460d8548dcbed Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 24 Jan 2024 11:04:55 +0000 Subject: [PATCH 341/676] interning doesn't check alignment anymroe, because it doesn't do any more projections. --- compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 6a92ed9717de5..8499de20498ff 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,5 +1,3 @@ -use std::mem; - use either::{Left, Right}; use rustc_hir::def::DefKind; @@ -75,9 +73,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( None => InternKind::Constant, } }; - let check_alignment = mem::replace(&mut ecx.machine.check_alignment, CheckAlignment::No); // interning doesn't need to respect alignment intern_const_alloc_recursive(ecx, intern_kind, &ret)?; - ecx.machine.check_alignment = check_alignment; debug!("eval_body_using_ecx done: {:?}", ret); Ok(ret) From b6d0225cafcf7d2421ad943647ed6ef4b8eb7bb4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 24 Jan 2024 11:05:14 +0000 Subject: [PATCH 342/676] prefer instrumentation over entry/exit tracing statements --- compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 8499de20498ff..a2d0f1c5583f3 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -22,12 +22,13 @@ use crate::interpret::{ }; // Returns a pointer to where the result lives +#[instrument(level = "trace", skip(ecx, body), ret)] fn eval_body_using_ecx<'mir, 'tcx>( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, cid: GlobalId<'tcx>, body: &'mir mir::Body<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env); + trace!(?ecx.param_env); let tcx = *ecx.tcx; assert!( cid.promoted.is_some() @@ -75,7 +76,6 @@ fn eval_body_using_ecx<'mir, 'tcx>( }; intern_const_alloc_recursive(ecx, intern_kind, &ret)?; - debug!("eval_body_using_ecx done: {:?}", ret); Ok(ret) } From a73c44889a6402f13d25fd5b973765ff62fb9885 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 24 Jan 2024 11:32:38 +0000 Subject: [PATCH 343/676] Prefer external iteration now that we don't actually recurse anymore --- .../rustc_const_eval/src/interpret/intern.rs | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 751fbfacaad00..48920ba384ada 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -41,13 +41,12 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine< /// allocation is interned immutably; if it is `Mutability::Mut`, then the allocation *must be* /// already mutable (as a sanity check). /// -/// `recursive_alloc` is called for all recursively encountered allocations. +/// Returns an iterator over all relocations referred to by this allocation. fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>( ecx: &'rt mut InterpCx<'mir, 'tcx, M>, alloc_id: AllocId, mutability: Mutability, - mut recursive_alloc: impl FnMut(&InterpCx<'mir, 'tcx, M>, CtfeProvenance), -) -> Result<(), ()> { +) -> Result + 'tcx, ()> { trace!("intern_shallow {:?}", alloc_id); // remove allocation let Some((_kind, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) else { @@ -65,14 +64,10 @@ fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>( assert_eq!(alloc.mutability, Mutability::Mut); } } - // record child allocations - for &(_, prov) in alloc.provenance().ptrs().iter() { - recursive_alloc(ecx, prov); - } // link the alloc id to the actual allocation let alloc = ecx.tcx.mk_const_alloc(alloc); ecx.tcx.set_alloc_id_memory(alloc_id, alloc); - Ok(()) + Ok(alloc.0.0.provenance().ptrs().iter().map(|&(_, prov)| prov)) } /// How a constant value should be interned. @@ -128,7 +123,7 @@ pub fn intern_const_alloc_recursive< } }; - // Initialize recursive interning. + // Intern the base allocation, and initialize todo list for recursive interning. let base_alloc_id = ret.ptr().provenance.unwrap().alloc_id(); let mut todo = vec![(base_alloc_id, base_mutability)]; // We need to distinguish "has just been interned" from "was already in `tcx`", @@ -154,7 +149,10 @@ pub fn intern_const_alloc_recursive< continue; } just_interned.insert(alloc_id); - intern_shallow(ecx, alloc_id, mutability, |ecx, prov| { + let provs = intern_shallow(ecx, alloc_id, mutability).map_err(|()| { + ecx.tcx.dcx().emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) + })?; + for prov in provs { let alloc_id = prov.alloc_id(); if intern_kind != InternKind::Promoted && inner_mutability == Mutability::Not @@ -169,7 +167,7 @@ pub fn intern_const_alloc_recursive< // during interning is to justify why we intern the *new* allocations immutably, // so we can completely ignore existing allocations. We also don't need to add // this to the todo list, since after all it is already interned. - return; + continue; } // Found a mutable pointer inside a const where inner allocations should be // immutable. We exclude promoteds from this, since things like `&mut []` and @@ -189,10 +187,7 @@ pub fn intern_const_alloc_recursive< // okay with losing some potential for immutability here. This can anyway only affect // `static mut`. todo.push((alloc_id, inner_mutability)); - }) - .map_err(|()| { - ecx.tcx.dcx().emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) - })?; + } } if found_bad_mutable_pointer { return Err(ecx @@ -220,13 +215,13 @@ pub fn intern_const_alloc_for_constprop< return Ok(()); } // Move allocation to `tcx`. - intern_shallow(ecx, alloc_id, Mutability::Not, |_ecx, _| { + for _ in intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))? { // We are not doing recursive interning, so we don't currently support provenance. // (If this assertion ever triggers, we should just implement a // proper recursive interning loop -- or just call `intern_const_alloc_recursive`. panic!("`intern_const_alloc_for_constprop` called on allocation with nested provenance") - }) - .map_err(|()| err_ub!(DeadLocal).into()) + } + Ok(()) } impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> @@ -247,15 +242,14 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> let dest = self.allocate(layout, MemoryKind::Stack)?; f(self, &dest.clone().into())?; let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance - intern_shallow(self, alloc_id, Mutability::Not, |ecx, prov| { + for prov in intern_shallow(self, alloc_id, Mutability::Not).unwrap() { // We are not doing recursive interning, so we don't currently support provenance. // (If this assertion ever triggers, we should just implement a // proper recursive interning loop -- or just call `intern_const_alloc_recursive`. - if !ecx.tcx.try_get_global_alloc(prov.alloc_id()).is_some() { + if !self.tcx.try_get_global_alloc(prov.alloc_id()).is_some() { panic!("`intern_with_temp_alloc` with nested allocations"); } - }) - .unwrap(); + } Ok(alloc_id) } } From a57a00ebf69722de2944d37de10946cf3aa6fe15 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 24 Jan 2024 11:46:57 +0000 Subject: [PATCH 344/676] separately intern the outermost alloc from the rest --- .../rustc_const_eval/src/interpret/intern.rs | 80 +++++++++---------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 48920ba384ada..7621d038855f5 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -125,10 +125,11 @@ pub fn intern_const_alloc_recursive< // Intern the base allocation, and initialize todo list for recursive interning. let base_alloc_id = ret.ptr().provenance.unwrap().alloc_id(); - let mut todo = vec![(base_alloc_id, base_mutability)]; + let mut todo: Vec<_> = + intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().map(|prov| prov).collect(); // We need to distinguish "has just been interned" from "was already in `tcx`", // so we track this in a separate set. - let mut just_interned = FxHashSet::default(); + let mut just_interned: FxHashSet<_> = std::iter::once(base_alloc_id).collect(); // Whether we encountered a bad mutable pointer. // We want to first report "dangling" and then "mutable", so we need to delay reporting these // errors. @@ -142,52 +143,49 @@ pub fn intern_const_alloc_recursive< // raw pointers, so we cannot rely on validation to catch them -- and since interning runs // before validation, and interning doesn't know the type of anything, this means we can't show // better errors. Maybe we should consider doing validation before interning in the future. - while let Some((alloc_id, mutability)) = todo.pop() { + while let Some(prov) = todo.pop() { + let alloc_id = prov.alloc_id(); + if intern_kind != InternKind::Promoted + && inner_mutability == Mutability::Not + && !prov.immutable() + { + if ecx.tcx.try_get_global_alloc(alloc_id).is_some() + && !just_interned.contains(&alloc_id) + { + // This is a pointer to some memory from another constant. We encounter mutable + // pointers to such memory since we do not always track immutability through + // these "global" pointers. Allowing them is harmless; the point of these checks + // during interning is to justify why we intern the *new* allocations immutably, + // so we can completely ignore existing allocations. We also don't need to add + // this to the todo list, since after all it is already interned. + continue; + } + // Found a mutable pointer inside a const where inner allocations should be + // immutable. We exclude promoteds from this, since things like `&mut []` and + // `&None::>` lead to promotion that can produce mutable pointers. We rely + // on the promotion analysis not screwing up to ensure that it is sound to intern + // promoteds as immutable. + found_bad_mutable_pointer = true; + } if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { // Already interned. debug_assert!(!ecx.memory.alloc_map.contains_key(&alloc_id)); continue; } just_interned.insert(alloc_id); - let provs = intern_shallow(ecx, alloc_id, mutability).map_err(|()| { + // We always intern with `inner_mutability`, and furthermore we ensured above that if + // that is "immutable", then there are *no* mutable pointers anywhere in the newly + // interned memory -- justifying that we can indeed intern immutably. However this also + // means we can *not* easily intern immutably here if `prov.immutable()` is true and + // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and + // we'd have to somehow check that they are *all* immutable before deciding that this + // allocation can be made immutable. In the future we could consider analyzing all + // pointers before deciding which allocations can be made immutable; but for now we are + // okay with losing some potential for immutability here. This can anyway only affect + // `static mut`. + todo.extend(intern_shallow(ecx, alloc_id, inner_mutability).map_err(|()| { ecx.tcx.dcx().emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) - })?; - for prov in provs { - let alloc_id = prov.alloc_id(); - if intern_kind != InternKind::Promoted - && inner_mutability == Mutability::Not - && !prov.immutable() - { - if ecx.tcx.try_get_global_alloc(alloc_id).is_some() - && !just_interned.contains(&alloc_id) - { - // This is a pointer to some memory from another constant. We encounter mutable - // pointers to such memory since we do not always track immutability through - // these "global" pointers. Allowing them is harmless; the point of these checks - // during interning is to justify why we intern the *new* allocations immutably, - // so we can completely ignore existing allocations. We also don't need to add - // this to the todo list, since after all it is already interned. - continue; - } - // Found a mutable pointer inside a const where inner allocations should be - // immutable. We exclude promoteds from this, since things like `&mut []` and - // `&None::>` lead to promotion that can produce mutable pointers. We rely - // on the promotion analysis not screwing up to ensure that it is sound to intern - // promoteds as immutable. - found_bad_mutable_pointer = true; - } - // We always intern with `inner_mutability`, and furthermore we ensured above that if - // that is "immutable", then there are *no* mutable pointers anywhere in the newly - // interned memory -- justifying that we can indeed intern immutably. However this also - // means we can *not* easily intern immutably here if `prov.immutable()` is true and - // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and - // we'd have to somehow check that they are *all* immutable before deciding that this - // allocation can be made immutable. In the future we could consider analyzing all - // pointers before deciding which allocations can be made immutable; but for now we are - // okay with losing some potential for immutability here. This can anyway only affect - // `static mut`. - todo.push((alloc_id, inner_mutability)); - } + })?); } if found_bad_mutable_pointer { return Err(ecx From 5d46b982c539ef3a227bd5557ec8a1648dfc5a5c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Jan 2024 10:38:17 +0000 Subject: [PATCH 345/676] Document base vs nested alloc interning --- compiler/rustc_const_eval/src/interpret/intern.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 7621d038855f5..c3a53f90e60a0 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -125,6 +125,9 @@ pub fn intern_const_alloc_recursive< // Intern the base allocation, and initialize todo list for recursive interning. let base_alloc_id = ret.ptr().provenance.unwrap().alloc_id(); + // First we intern the base allocation, as it requires a different mutability. + // This gives us the initial set of nested allocations, which will then all be processed + // recursively in the loop below. let mut todo: Vec<_> = intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().map(|prov| prov).collect(); // We need to distinguish "has just been interned" from "was already in `tcx`", From 83fa46fe5bcf8324aaa0614212080486623d672b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 26 Jan 2024 13:23:55 +0000 Subject: [PATCH 346/676] Borrow check inline const patterns Add type annotations to MIR so that borrowck can pass constraints from inline constants in patterns to the containing function. --- compiler/rustc_borrowck/src/type_check/mod.rs | 64 ++++++++++++++++--- .../src/build/matches/simplify.rs | 37 ++++++++++- .../const-match-pat-lifetime-err.rs | 25 ++++++-- .../const-match-pat-lifetime-err.stderr | 28 ++++++++ 4 files changed, 139 insertions(+), 15 deletions(-) create mode 100644 tests/ui/inline-const/const-match-pat-lifetime-err.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index cf28e62177fb4..488dfc64cf6f0 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1099,10 +1099,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self), level = "debug")] fn check_user_type_annotations(&mut self) { debug!(?self.user_type_annotations); + let tcx = self.tcx(); for user_annotation in self.user_type_annotations { let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty); - self.ascribe_user_type(inferred_ty, annotation, span); + if let ty::UserType::TypeOf(def, args) = annotation + && let DefKind::InlineConst = tcx.def_kind(def) + { + self.check_inline_const(inferred_ty, def.expect_local(), args, span); + } else { + self.ascribe_user_type(inferred_ty, annotation, span); + } } } @@ -1195,6 +1202,36 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Ok(()) } + fn check_inline_const( + &mut self, + inferred_ty: Ty<'tcx>, + def_id: LocalDefId, + args: UserArgs<'tcx>, + span: Span, + ) { + assert!(args.user_self_ty.is_none()); + let tcx = self.tcx(); + let const_ty = tcx.type_of(def_id).instantiate(tcx, args.args); + if let Err(terr) = + self.eq_types(const_ty, inferred_ty, Locations::All(span), ConstraintCategory::Boring) + { + span_bug!( + span, + "bad inline const pattern: ({:?} = {:?}) {:?}", + const_ty, + inferred_ty, + terr + ); + } + let args = self.infcx.resolve_vars_if_possible(args.args); + let predicates = self.prove_closure_bounds(tcx, def_id, args, Locations::All(span)); + self.normalize_and_prove_instantiated_predicates( + def_id.to_def_id(), + predicates, + Locations::All(span), + ); + } + fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -1851,7 +1888,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let def_id = uv.def; if tcx.def_kind(def_id) == DefKind::InlineConst { let def_id = def_id.expect_local(); - let predicates = self.prove_closure_bounds(tcx, def_id, uv.args, location); + let predicates = self.prove_closure_bounds( + tcx, + def_id, + uv.args, + location.to_locations(), + ); self.normalize_and_prove_instantiated_predicates( def_id.to_def_id(), predicates, @@ -2654,9 +2696,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // desugaring. A closure gets desugared to a struct, and // these extra requirements are basically like where // clauses on the struct. - AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args) => { - (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), args, location)) - } + AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args) => ( + def_id, + self.prove_closure_bounds( + tcx, + def_id.expect_local(), + args, + location.to_locations(), + ), + ), AggregateKind::Array(_) | AggregateKind::Tuple => { (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty()) @@ -2675,7 +2723,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { tcx: TyCtxt<'tcx>, def_id: LocalDefId, args: GenericArgsRef<'tcx>, - location: Location, + locations: Locations, ) -> ty::InstantiatedPredicates<'tcx> { if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements { constraint_conversion::ConstraintConversion::new( @@ -2684,7 +2732,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.region_bound_pairs, self.implicit_region_bound, self.param_env, - location.to_locations(), + locations, DUMMY_SP, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. self.borrowck_context.constraints, @@ -2710,7 +2758,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(_) = self.eq_args( typeck_root_args, parent_args, - location.to_locations(), + locations, ConstraintCategory::BoringNoLocation, ) { span_mirbug!( diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index a7f6f4873e383..065c93e86a866 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -15,7 +15,9 @@ use crate::build::expr::as_place::PlaceBuilder; use crate::build::matches::{Ascription, Binding, Candidate, MatchPair}; use crate::build::Builder; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::thir::{self, *}; +use rustc_middle::ty; use std::mem; @@ -149,7 +151,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ref subpattern, ascription: thir::Ascription { ref annotation, variance }, } => { - // Apply the type ascription to the value at `match_pair.place`, which is the + // Apply the type ascription to the value at `match_pair.place` if let Some(source) = match_pair.place.try_to_place(self) { candidate.ascriptions.push(Ascription { annotation: annotation.clone(), @@ -205,7 +207,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Err(match_pair) } - PatKind::InlineConstant { subpattern: ref pattern, def: _ } => { + PatKind::InlineConstant { subpattern: ref pattern, def } => { + // Apply a type ascription for the inline constant to the value at `match_pair.place` + if let Some(source) = match_pair.place.try_to_place(self) { + let span = match_pair.pattern.span; + let parent_id = self.tcx.typeck_root_def_id(self.def_id.to_def_id()); + let args = ty::InlineConstArgs::new( + self.tcx, + ty::InlineConstArgsParts { + parent_args: ty::GenericArgs::identity_for_item(self.tcx, parent_id), + ty: self.infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + }), + }, + ) + .args; + let user_ty = + self.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf( + def.to_def_id(), + ty::UserArgs { args, user_self_ty: None }, + )); + let annotation = ty::CanonicalUserTypeAnnotation { + inferred_ty: pattern.ty, + span, + user_ty: Box::new(user_ty), + }; + candidate.ascriptions.push(Ascription { + annotation, + source, + variance: ty::Contravariant, + }); + } candidate.match_pairs.push(MatchPair::new(match_pair.place, pattern, self)); Ok(()) 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 366ad26bb2716..ce91e5233bccd 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.rs +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.rs @@ -1,5 +1,3 @@ -// ignore-test (This is currently broken) - #![allow(incomplete_features)] #![feature(const_mut_refs)] #![feature(inline_const_pat)] @@ -9,6 +7,9 @@ use std::marker::PhantomData; #[derive(PartialEq, Eq)] pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); +#[derive(PartialEq, Eq)] +pub struct CovariantRef<'a, T: ?Sized>(&'a T); + impl<'a, T: ?Sized> InvariantRef<'a, T> { pub const fn new(r: &'a T) -> Self { InvariantRef(r, PhantomData) @@ -19,16 +20,30 @@ impl<'a> InvariantRef<'a, ()> { pub const NEW: Self = InvariantRef::new(&()); } +impl<'a> CovariantRef<'a, ()> { + pub const NEW: Self = CovariantRef(&()); +} + fn match_invariant_ref<'a>() { let y = (); match InvariantRef::new(&y) { - //~^ ERROR `y` does not live long enough [E0597] - // FIXME(nbdd0121): This should give the same error as `InvariantRef::<'a>::NEW` (without - // const block) + //~^ ERROR `y` does not live long enough [E0597] const { InvariantRef::<'a>::NEW } => (), } } +fn match_covariant_ref<'a>() { + // Unclear if we should error here (should we be able to subtype the type of + // `y.0`), but using the associated const directly in the pattern also + // errors. + let y: (CovariantRef<'static, _>,) = (CovariantRef(&()),); + //~^ ERROR lifetime may not live long enough + match y.0 { + const { CovariantRef::<'a>::NEW } => (), + } +} + fn main() { match_invariant_ref(); + match_covariant_ref(); } diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr new file mode 100644 index 0000000000000..c5760f1027ef2 --- /dev/null +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr @@ -0,0 +1,28 @@ +error[E0597]: `y` does not live long enough + --> $DIR/const-match-pat-lifetime-err.rs:29:29 + | +LL | fn match_invariant_ref<'a>() { + | -- lifetime `'a` defined here +LL | let y = (); + | - binding `y` declared here +LL | match InvariantRef::new(&y) { + | ^^ borrowed value does not live long enough +LL | +LL | const { InvariantRef::<'a>::NEW } => (), + | --------------------------------- type annotation requires that `y` is borrowed for `'a` +LL | } +LL | } + | - `y` dropped here while still borrowed + +error: lifetime may not live long enough + --> $DIR/const-match-pat-lifetime-err.rs:39:12 + | +LL | fn match_covariant_ref<'a>() { + | -- lifetime `'a` defined here +... +LL | let y: (CovariantRef<'static, _>,) = (CovariantRef(&()),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. From 44824e0bcedcbd3e5a43c1cf51c26ee20a585637 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 26 Jan 2024 13:24:23 +0000 Subject: [PATCH 347/676] Enable tests for unsafe blocks in inline const patterns --- tests/ui/inline-const/pat-unsafe-err.rs | 2 -- tests/ui/inline-const/pat-unsafe-err.stderr | 19 +++++++++++++++++++ tests/ui/inline-const/pat-unsafe.rs | 1 - tests/ui/inline-const/pat-unsafe.stderr | 20 ++++++++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/ui/inline-const/pat-unsafe-err.stderr create mode 100644 tests/ui/inline-const/pat-unsafe.stderr diff --git a/tests/ui/inline-const/pat-unsafe-err.rs b/tests/ui/inline-const/pat-unsafe-err.rs index 0db18dd3260d0..7680c82efb5c5 100644 --- a/tests/ui/inline-const/pat-unsafe-err.rs +++ b/tests/ui/inline-const/pat-unsafe-err.rs @@ -1,5 +1,3 @@ -// ignore-test This is currently broken - #![allow(incomplete_features)] #![feature(inline_const_pat)] diff --git a/tests/ui/inline-const/pat-unsafe-err.stderr b/tests/ui/inline-const/pat-unsafe-err.stderr new file mode 100644 index 0000000000000..9b995d6ccf27e --- /dev/null +++ b/tests/ui/inline-const/pat-unsafe-err.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block + --> $DIR/pat-unsafe-err.rs:11:13 + | +LL | require_unsafe(); + | ^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block + --> $DIR/pat-unsafe-err.rs:18:13 + | +LL | require_unsafe() + | ^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/inline-const/pat-unsafe.rs b/tests/ui/inline-const/pat-unsafe.rs index cfef9ad6a563e..f7073ef40eb09 100644 --- a/tests/ui/inline-const/pat-unsafe.rs +++ b/tests/ui/inline-const/pat-unsafe.rs @@ -1,5 +1,4 @@ // check-pass -// ignore-test This is currently broken #![allow(incomplete_features)] #![warn(unused_unsafe)] diff --git a/tests/ui/inline-const/pat-unsafe.stderr b/tests/ui/inline-const/pat-unsafe.stderr new file mode 100644 index 0000000000000..84dc10c490258 --- /dev/null +++ b/tests/ui/inline-const/pat-unsafe.stderr @@ -0,0 +1,20 @@ +warning: unnecessary `unsafe` block + --> $DIR/pat-unsafe.rs:16:17 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/pat-unsafe.rs:4:9 + | +LL | #![warn(unused_unsafe)] + | ^^^^^^^^^^^^^ + +warning: unnecessary `unsafe` block + --> $DIR/pat-unsafe.rs:23:17 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +warning: 2 warnings emitted + From 492df34eea0215abb6e3e43dcdcef30df7be23f2 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 27 Jan 2024 19:09:55 +0800 Subject: [PATCH 348/676] Supress unhelpful diagnostics for unresolved top level attributes --- compiler/rustc_errors/src/lib.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 12 +++++- compiler/rustc_resolve/src/macros.rs | 32 +++++++------- tests/ui/derives/issue-36617.rs | 10 ++--- tests/ui/derives/issue-36617.stderr | 42 +------------------ tests/ui/extenv/issue-55897.rs | 1 - tests/ui/extenv/issue-55897.stderr | 14 ++----- .../issue-43106-gating-of-bench.rs | 3 +- .../issue-43106-gating-of-bench.stderr | 12 +----- .../issue-43106-gating-of-test.rs | 3 +- .../issue-43106-gating-of-test.stderr | 12 +----- tests/ui/imports/issue-28134.rs | 2 +- tests/ui/imports/issue-28134.stderr | 10 +---- tests/ui/imports/issue-55457.rs | 7 ++-- tests/ui/imports/issue-55457.stderr | 36 +--------------- tests/ui/imports/issue-59764.rs | 1 - tests/ui/imports/issue-59764.stderr | 12 +----- .../derive-helper-legacy-spurious.rs | 2 +- .../derive-helper-legacy-spurious.stderr | 10 +---- .../issue-118455-skip-err-builtin.rs | 6 +++ .../issue-118455-skip-err-builtin.stderr | 8 ++++ ...est-fix-invalid-top-level-macro-attr.fixed | 6 +++ ...uggest-fix-invalid-top-level-macro-attr.rs | 6 +++ ...st-fix-invalid-top-level-macro-attr.stderr | 16 +++++++ tests/ui/reserved/reserved-attr-on-macro.rs | 2 +- .../ui/reserved/reserved-attr-on-macro.stderr | 10 +---- tests/ui/rust-2018/issue-54006.rs | 1 - tests/ui/rust-2018/issue-54006.stderr | 10 +---- tests/ui/span/issue-43927-non-ADT-derive.rs | 3 +- .../ui/span/issue-43927-non-ADT-derive.stderr | 12 +----- 30 files changed, 100 insertions(+), 202 deletions(-) create mode 100644 tests/ui/proc-macro/issue-118455-skip-err-builtin.rs create mode 100644 tests/ui/proc-macro/issue-118455-skip-err-builtin.stderr create mode 100644 tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed create mode 100644 tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs create mode 100644 tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 6d9208341a5c0..8b6abe0ff5a19 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -514,6 +514,7 @@ pub enum StashKey { MaybeForgetReturn, /// Query cycle detected, stashing in favor of a better error. Cycle, + UndeterminedMacroResolution, } fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9d9741bbe8947..5886378c0b76f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -5,8 +5,10 @@ //! item. use crate::{errors, fluent_generated as fluent}; -use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; +use rustc_ast::{ast, AttrKind, AttrStyle, Attribute, LitKind}; +use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::StashKey; use rustc_errors::{Applicability, DiagCtxt, IntoDiagnosticArg, MultiSpan}; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; @@ -2530,6 +2532,14 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { if attr.style == AttrStyle::Inner { for attr_to_check in ATTRS_TO_CHECK { if attr.has_name(*attr_to_check) { + if let AttrKind::Normal(ref p) = attr.kind + && let Some(diag) = tcx.dcx().steal_diagnostic( + p.item.path.span, + StashKey::UndeterminedMacroResolution, + ) + { + diag.cancel(); + } let item = tcx .hir() .items() diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index a6bf289a76a4c..170cc1268c39d 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1,10 +1,9 @@ //! A bunch of methods and structures more or less related to resolving macros and //! interface provided by `Resolver` to macro expander. -use crate::errors::{ - self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope, - MacroExpectedFound, RemoveSurroundingDerive, -}; +use crate::errors::CannotDetermineMacroResolution; +use crate::errors::{self, AddAsNonDerive, CannotFindIdentInThisScope}; +use crate::errors::{MacroExpectedFound, RemoveSurroundingDerive}; use crate::Namespace::*; use crate::{BuiltinMacroState, Determinacy, MacroData}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; @@ -15,7 +14,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; -use rustc_errors::{codes::*, struct_span_code_err, Applicability}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability, StashKey}; use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; @@ -25,9 +24,8 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::RegisteredTools; use rustc_middle::ty::{TyCtxt, Visibility}; -use rustc_session::lint::builtin::{ - LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, -}; +use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; +use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE}; use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::feature_err; @@ -703,21 +701,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // situations should be reported as errors, so this is a bug. this.dcx().span_delayed_bug(span, "inconsistent resolution for a macro"); } - } else { + } else if this.tcx.dcx().has_errors().is_none() && this.privacy_errors.is_empty() { // It's possible that the macro was unresolved (indeterminate) and silently // expanded into a dummy fragment for recovery during expansion. // Now, post-expansion, the resolution may succeed, but we can't change the // past and need to report an error. // However, non-speculative `resolve_path` can successfully return private items // even if speculative `resolve_path` returned nothing previously, so we skip this - // less informative error if the privacy error is reported elsewhere. - if this.privacy_errors.is_empty() { - this.dcx().emit_err(CannotDetermineMacroResolution { - span, - kind: kind.descr(), - path: Segment::names_to_string(path), - }); - } + // less informative error if no other error is reported elsewhere. + + let err = this.dcx().create_err(CannotDetermineMacroResolution { + span, + kind: kind.descr(), + path: Segment::names_to_string(path), + }); + err.stash(span, StashKey::UndeterminedMacroResolution); } }; diff --git a/tests/ui/derives/issue-36617.rs b/tests/ui/derives/issue-36617.rs index 08f293d2ebb06..236ec7748cbdd 100644 --- a/tests/ui/derives/issue-36617.rs +++ b/tests/ui/derives/issue-36617.rs @@ -1,16 +1,16 @@ -#![derive(Copy)] //~ ERROR cannot determine resolution for the attribute macro `derive` +#![derive(Copy)] //~^ ERROR `derive` attribute cannot be used at crate level -#![test]//~ ERROR cannot determine resolution for the attribute macro `test` +#![test] //~^ ERROR `test` attribute cannot be used at crate level -#![test_case]//~ ERROR cannot determine resolution for the attribute macro `test_case` +#![test_case] //~^ ERROR `test_case` attribute cannot be used at crate level -#![bench]//~ ERROR cannot determine resolution for the attribute macro `bench` +#![bench] //~^ ERROR `bench` attribute cannot be used at crate level -#![global_allocator]//~ ERROR cannot determine resolution for the attribute macro `global_allocator` +#![global_allocator] //~^ ERROR `global_allocator` attribute cannot be used at crate level fn main() {} diff --git a/tests/ui/derives/issue-36617.stderr b/tests/ui/derives/issue-36617.stderr index 98be7963e5ef9..3de1d87c5046c 100644 --- a/tests/ui/derives/issue-36617.stderr +++ b/tests/ui/derives/issue-36617.stderr @@ -1,43 +1,3 @@ -error: cannot determine resolution for the attribute macro `derive` - --> $DIR/issue-36617.rs:1:4 - | -LL | #![derive(Copy)] - | ^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-36617.rs:4:4 - | -LL | #![test] - | ^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `test_case` - --> $DIR/issue-36617.rs:7:4 - | -LL | #![test_case] - | ^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `bench` - --> $DIR/issue-36617.rs:10:4 - | -LL | #![bench] - | ^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `global_allocator` - --> $DIR/issue-36617.rs:13:4 - | -LL | #![global_allocator] - | ^^^^^^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `derive` attribute cannot be used at crate level --> $DIR/issue-36617.rs:1:1 | @@ -113,5 +73,5 @@ LL - #![global_allocator] LL + #[global_allocator] | -error: aborting due to 10 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/extenv/issue-55897.rs b/tests/ui/extenv/issue-55897.rs index b7533f41351da..b6500e5405933 100644 --- a/tests/ui/extenv/issue-55897.rs +++ b/tests/ui/extenv/issue-55897.rs @@ -4,7 +4,6 @@ mod unresolved_env { use env; //~ ERROR unresolved import `env` include!(concat!(env!("NON_EXISTENT"), "/data.rs")); - //~^ ERROR cannot determine resolution for the macro `env` } mod nonexistent_env { diff --git a/tests/ui/extenv/issue-55897.stderr b/tests/ui/extenv/issue-55897.stderr index 401db827813a9..2e8c05cca867f 100644 --- a/tests/ui/extenv/issue-55897.stderr +++ b/tests/ui/extenv/issue-55897.stderr @@ -1,5 +1,5 @@ error: environment variable `NON_EXISTENT` not defined at compile time - --> $DIR/issue-55897.rs:11:22 + --> $DIR/issue-55897.rs:10:22 | LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: suffixes on string literals are invalid - --> $DIR/issue-55897.rs:16:22 + --> $DIR/issue-55897.rs:15:22 | LL | include!(concat!("NON_EXISTENT"suffix, "/data.rs")); | ^^^^^^^^^^^^^^^^^^^^ invalid suffix `suffix` @@ -33,14 +33,6 @@ help: consider importing this module instead LL | use std::env; | ~~~~~~~~ -error: cannot determine resolution for the macro `env` - --> $DIR/issue-55897.rs:6:22 - | -LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); - | ^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.rs b/tests/ui/feature-gates/issue-43106-gating-of-bench.rs index 796325b79af66..841383a008f54 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-bench.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.rs @@ -5,6 +5,5 @@ #![feature(custom_inner_attributes)] #![bench = "4100"] -//~^ ERROR cannot determine resolution for the attribute macro `bench` -//~^^ ERROR `bench` attribute cannot be used at crate level +//~^ ERROR `bench` attribute cannot be used at crate level fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr index 8270d46d492a9..912c2746f3835 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr @@ -1,17 +1,9 @@ -error: cannot determine resolution for the attribute macro `bench` - --> $DIR/issue-43106-gating-of-bench.rs:7:4 - | -LL | #![bench = "4100"] - | ^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `bench` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-bench.rs:7:1 | LL | #![bench = "4100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +LL | LL | fn main() {} | ---- the inner attribute doesn't annotate this function | @@ -21,5 +13,5 @@ LL - #![bench = "4100"] LL + #[bench = "4100"] | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.rs b/tests/ui/feature-gates/issue-43106-gating-of-test.rs index 39835c9268eef..38c92d933fdd8 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-test.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-test.rs @@ -2,6 +2,5 @@ #![allow(soft_unstable)] #![test = "4200"] -//~^ ERROR cannot determine resolution for the attribute macro `test` -//~^^ ERROR `test` attribute cannot be used at crate level +//~^ ERROR `test` attribute cannot be used at crate level fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr index 922c9861aa3c1..2fc220dc47bd1 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr @@ -1,17 +1,9 @@ -error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-43106-gating-of-test.rs:4:4 - | -LL | #![test = "4200"] - | ^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `test` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-test.rs:4:1 | LL | #![test = "4200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +LL | LL | fn main() {} | ---- the inner attribute doesn't annotate this function | @@ -21,5 +13,5 @@ LL - #![test = "4200"] LL + #[test = "4200"] | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-28134.rs b/tests/ui/imports/issue-28134.rs index ef2a5d634a678..0cecdf7a0ec73 100644 --- a/tests/ui/imports/issue-28134.rs +++ b/tests/ui/imports/issue-28134.rs @@ -1,5 +1,5 @@ // compile-flags: --test #![allow(soft_unstable)] -#![test] //~ ERROR cannot determine resolution for the attribute macro `test` +#![test] //~^ ERROR 4:1: 4:9: `test` attribute cannot be used at crate level diff --git a/tests/ui/imports/issue-28134.stderr b/tests/ui/imports/issue-28134.stderr index 5315c2e9fee9c..e47aa15e87a94 100644 --- a/tests/ui/imports/issue-28134.stderr +++ b/tests/ui/imports/issue-28134.stderr @@ -1,11 +1,3 @@ -error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-28134.rs:4:4 - | -LL | #![test] - | ^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `test` attribute cannot be used at crate level --> $DIR/issue-28134.rs:4:1 | @@ -18,5 +10,5 @@ LL - #![test] LL + #[test] | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-55457.rs b/tests/ui/imports/issue-55457.rs index c1f048897d9ea..fd08294025587 100644 --- a/tests/ui/imports/issue-55457.rs +++ b/tests/ui/imports/issue-55457.rs @@ -1,10 +1,9 @@ use NonExistent; //~ ERROR unresolved import `NonExistent` use non_existent::non_existent; //~ ERROR unresolved import `non_existent` -#[non_existent] //~ ERROR cannot determine resolution for the attribute macro `non_existent` -#[derive(NonExistent)] //~ ERROR cannot determine resolution for the derive macro `NonExistent` - //~| ERROR cannot determine resolution for the derive macro `NonExistent` - //~| ERROR cannot determine resolution for the derive macro `NonExistent` +#[non_existent] +#[derive(NonExistent)] + struct S; fn main() {} diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr index 30d2373652b4c..09bb13a060478 100644 --- a/tests/ui/imports/issue-55457.stderr +++ b/tests/ui/imports/issue-55457.stderr @@ -15,40 +15,6 @@ LL | use non_existent::non_existent; | = help: consider adding `extern crate non_existent` to use the `non_existent` crate -error: cannot determine resolution for the derive macro `NonExistent` - --> $DIR/issue-55457.rs:5:10 - | -LL | #[derive(NonExistent)] - | ^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `non_existent` - --> $DIR/issue-55457.rs:4:3 - | -LL | #[non_existent] - | ^^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the derive macro `NonExistent` - --> $DIR/issue-55457.rs:5:10 - | -LL | #[derive(NonExistent)] - | ^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: cannot determine resolution for the derive macro `NonExistent` - --> $DIR/issue-55457.rs:5:10 - | -LL | #[derive(NonExistent)] - | ^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-59764.rs b/tests/ui/imports/issue-59764.rs index 09dee8c273268..91b3ddcd84d57 100644 --- a/tests/ui/imports/issue-59764.rs +++ b/tests/ui/imports/issue-59764.rs @@ -128,7 +128,6 @@ use issue_59764::foo::makro; //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] makro!(bar); -//~^ ERROR cannot determine resolution for the macro `makro` fn main() { bar(); diff --git a/tests/ui/imports/issue-59764.stderr b/tests/ui/imports/issue-59764.stderr index b969515e2f0e6..fe58eb97b8dbf 100644 --- a/tests/ui/imports/issue-59764.stderr +++ b/tests/ui/imports/issue-59764.stderr @@ -226,21 +226,13 @@ help: a macro with this name exists at the root of the crate LL | use issue_59764::makro; | ~~~~~~~~~~~~~~~~~~ -error: cannot determine resolution for the macro `makro` - --> $DIR/issue-59764.rs:130:1 - | -LL | makro!(bar); - | ^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error[E0425]: cannot find function `bar` in this scope - --> $DIR/issue-59764.rs:134:5 + --> $DIR/issue-59764.rs:133:5 | LL | bar(); | ^^^ not found in this scope -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors Some errors have detailed explanations: E0425, E0432. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs index 4a7e48eed46c3..b484b42e56672 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs @@ -5,7 +5,7 @@ #[macro_use] extern crate test_macros; -#[derive(Empty)] //~ ERROR cannot determine resolution for the attribute macro `derive` +#[derive(Empty)] #[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope struct Foo {} diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr b/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr index fd1ed8a3d0ff3..b34713b8ca68e 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr @@ -4,19 +4,11 @@ error: cannot find attribute `dummy` in this scope LL | #![dummy] | ^^^^^ -error: cannot determine resolution for the attribute macro `derive` - --> $DIR/derive-helper-legacy-spurious.rs:8:3 - | -LL | #[derive(Empty)] - | ^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: cannot find attribute `empty_helper` in this scope --> $DIR/derive-helper-legacy-spurious.rs:9:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/issue-118455-skip-err-builtin.rs b/tests/ui/proc-macro/issue-118455-skip-err-builtin.rs new file mode 100644 index 0000000000000..baef020612891 --- /dev/null +++ b/tests/ui/proc-macro/issue-118455-skip-err-builtin.rs @@ -0,0 +1,6 @@ +#![some_nonexistent_attribute] +//~^ ERROR cannot find attribute `some_nonexistent_attribute` in this scope +#[derive(Debug)] +pub struct SomeUserCode; + +fn main() {} diff --git a/tests/ui/proc-macro/issue-118455-skip-err-builtin.stderr b/tests/ui/proc-macro/issue-118455-skip-err-builtin.stderr new file mode 100644 index 0000000000000..fa8af87a3d019 --- /dev/null +++ b/tests/ui/proc-macro/issue-118455-skip-err-builtin.stderr @@ -0,0 +1,8 @@ +error: cannot find attribute `some_nonexistent_attribute` in this scope + --> $DIR/issue-118455-skip-err-builtin.rs:1:4 + | +LL | #![some_nonexistent_attribute] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed new file mode 100644 index 0000000000000..ae5f9f86726f3 --- /dev/null +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +#[derive(Debug)] //~ ERROR `derive` attribute cannot be used at crate level +struct Test {} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs new file mode 100644 index 0000000000000..639c64f8827c5 --- /dev/null +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs @@ -0,0 +1,6 @@ +// run-rustfix + +#![derive(Debug)] //~ ERROR `derive` attribute cannot be used at crate level +struct Test {} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr new file mode 100644 index 0000000000000..f62cdd14b873f --- /dev/null +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr @@ -0,0 +1,16 @@ +error: `derive` attribute cannot be used at crate level + --> $DIR/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs:3:1 + | +LL | #![derive(Debug)] + | ^^^^^^^^^^^^^^^^^ +LL | struct Test {} + | ---- the inner attribute doesn't annotate this struct + | +help: perhaps you meant to use an outer attribute + | +LL - #![derive(Debug)] +LL + #[derive(Debug)] + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/reserved/reserved-attr-on-macro.rs b/tests/ui/reserved/reserved-attr-on-macro.rs index 2630db0d09785..5c4657e0ec2e1 100644 --- a/tests/ui/reserved/reserved-attr-on-macro.rs +++ b/tests/ui/reserved/reserved-attr-on-macro.rs @@ -7,5 +7,5 @@ macro_rules! foo { } fn main() { - foo!(); //~ ERROR cannot determine resolution for the macro `foo` + foo!(); } diff --git a/tests/ui/reserved/reserved-attr-on-macro.stderr b/tests/ui/reserved/reserved-attr-on-macro.stderr index e55b58bef2855..066f72367b1a5 100644 --- a/tests/ui/reserved/reserved-attr-on-macro.stderr +++ b/tests/ui/reserved/reserved-attr-on-macro.stderr @@ -4,19 +4,11 @@ error: attributes starting with `rustc` are reserved for use by the `rustc` comp LL | #[rustc_attribute_should_be_reserved] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: cannot determine resolution for the macro `foo` - --> $DIR/reserved-attr-on-macro.rs:10:5 - | -LL | foo!(); - | ^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: cannot find attribute `rustc_attribute_should_be_reserved` in this scope --> $DIR/reserved-attr-on-macro.rs:1:3 | LL | #[rustc_attribute_should_be_reserved] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/rust-2018/issue-54006.rs b/tests/ui/rust-2018/issue-54006.rs index a7a4770fc02f9..6f929731c7674 100644 --- a/tests/ui/rust-2018/issue-54006.rs +++ b/tests/ui/rust-2018/issue-54006.rs @@ -8,6 +8,5 @@ use alloc::vec; pub fn foo() { let mut xs = vec![]; - //~^ ERROR cannot determine resolution for the macro `vec` xs.push(0); } diff --git a/tests/ui/rust-2018/issue-54006.stderr b/tests/ui/rust-2018/issue-54006.stderr index 1978138a68878..35d4c17d2c7f1 100644 --- a/tests/ui/rust-2018/issue-54006.stderr +++ b/tests/ui/rust-2018/issue-54006.stderr @@ -4,14 +4,6 @@ error[E0432]: unresolved import `alloc` LL | use alloc::vec; | ^^^^^ help: a similar path exists: `core::alloc` -error: cannot determine resolution for the macro `vec` - --> $DIR/issue-54006.rs:10:18 - | -LL | let mut xs = vec![]; - | ^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/span/issue-43927-non-ADT-derive.rs b/tests/ui/span/issue-43927-non-ADT-derive.rs index 935bfa001bfc6..e50ee36d7de95 100644 --- a/tests/ui/span/issue-43927-non-ADT-derive.rs +++ b/tests/ui/span/issue-43927-non-ADT-derive.rs @@ -1,6 +1,5 @@ #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! -//~^ ERROR cannot determine resolution for the attribute macro `derive` -//~^^ ERROR `derive` attribute cannot be used at crate level +//~^ ERROR `derive` attribute cannot be used at crate level struct DerivedOn; fn main() {} diff --git a/tests/ui/span/issue-43927-non-ADT-derive.stderr b/tests/ui/span/issue-43927-non-ADT-derive.stderr index a22a4d2b40a8e..27ed561f5be8a 100644 --- a/tests/ui/span/issue-43927-non-ADT-derive.stderr +++ b/tests/ui/span/issue-43927-non-ADT-derive.stderr @@ -1,17 +1,9 @@ -error: cannot determine resolution for the attribute macro `derive` - --> $DIR/issue-43927-non-ADT-derive.rs:1:4 - | -LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! - | ^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `derive` attribute cannot be used at crate level --> $DIR/issue-43927-non-ADT-derive.rs:1:1 | LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +LL | LL | struct DerivedOn; | --------- the inner attribute doesn't annotate this struct | @@ -21,5 +13,5 @@ LL - #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! LL + #[derive(Debug, PartialEq, Eq)] // should be an outer attribute! | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error From 1b17d8e1a03315dc9196c69fcfbcc2af165b175f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 29 Jan 2024 10:02:59 +0000 Subject: [PATCH 349/676] Add matthewjasper to some review groups --- triagebot.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index e57dd158374f8..34b795f49fb17 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -717,6 +717,7 @@ arena = [ mir = [ "@davidtwco", "@oli-obk", + "@matthewjasper" ] mir-opt = [ "@oli-obk", @@ -733,6 +734,7 @@ types = [ borrowck = [ "@davidtwco", "@pnkfelix", + "@matthewjasper" ] ast_lowering = [ "@compiler-errors", @@ -776,6 +778,7 @@ project-stable-mir = [ "/compiler/rustc_data_structures/src/stable_hasher.rs" = ["compiler", "incremental"] "/compiler/rustc_hir_analysis" = ["compiler", "types"] "/compiler/rustc_incremental" = ["compiler", "incremental"] +"/compiler/rustc_borrowck" = ["compiler", "borrowck"] "/compiler/rustc_lexer" = ["compiler", "lexer"] "/compiler/rustc_llvm" = ["@cuviper"] "/compiler/rustc_codegen_llvm/src/debuginfo" = ["compiler", "debuginfo"] @@ -785,6 +788,7 @@ project-stable-mir = [ "/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"] "/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"] "/compiler/rustc_mir_build/src/build" = ["compiler", "mir"] +"/compiler/rustc_mir_transform" = ["compiler", "mir", "mir-opt"] "/compiler/rustc_smir" = ["project-stable-mir"] "/compiler/rustc_parse" = ["compiler", "parser"] "/compiler/rustc_parse/src/lexer" = ["compiler", "lexer"] From 618110256752ce2c3b5873b51f458609cca901bc Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Mon, 29 Jan 2024 18:42:41 +0800 Subject: [PATCH 350/676] 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 351/676] 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 1bdeeef0d59f5539d045b65865f8b0ec7d76eed0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 28 Jan 2024 11:42:32 +0100 Subject: [PATCH 352/676] Update pulldown-cmark version to 0.9.5 --- Cargo.lock | 6 +++--- compiler/rustc_resolve/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09eb0d98efc90..3af93251fddd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3005,11 +3005,11 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "memchr", "unicase", ] diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index a1a353ce0574e..b6ae54010c242 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -pulldown-cmark = { version = "0.9.3", default-features = false } +pulldown-cmark = { version = "0.9.6", default-features = false } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } From 1e60cc9bd9b35c1aa63e941fad0c0326db82e366 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 28 Jan 2024 11:42:50 +0100 Subject: [PATCH 353/676] Add regression test for #100638 --- ...otnote-definition-without-blank-line-100638.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/rustdoc/footnote-definition-without-blank-line-100638.rs diff --git a/tests/rustdoc/footnote-definition-without-blank-line-100638.rs b/tests/rustdoc/footnote-definition-without-blank-line-100638.rs new file mode 100644 index 0000000000000..b6f62c3bcba57 --- /dev/null +++ b/tests/rustdoc/footnote-definition-without-blank-line-100638.rs @@ -0,0 +1,15 @@ +#![crate_name = "foo"] + +//! Reference to footnotes A[^1], B[^2] and C[^3]. +//! +//! [^1]: Footnote A. +//! [^2]: Footnote B. +//! [^3]: Footnote C. + +// @has 'foo/index.html' +// @has - '//*[@class="docblock"]/*[@class="footnotes"]/ol/li[@id="fn1"]/p' 'Footnote A' +// @has - '//li[@id="fn1"]/p/a/@href' '#fnref1' +// @has - '//*[@class="docblock"]/*[@class="footnotes"]/ol/li[@id="fn2"]/p' 'Footnote B' +// @has - '//li[@id="fn2"]/p/a/@href' '#fnref2' +// @has - '//*[@class="docblock"]/*[@class="footnotes"]/ol/li[@id="fn3"]/p' 'Footnote C' +// @has - '//li[@id="fn3"]/p/a/@href' '#fnref3' From 0d71860368094f21b2865c55685fe76a8e4a5874 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 8 Jan 2024 15:29:44 +0100 Subject: [PATCH 354/676] bye bye `assemble_candidates_via_self_ty` --- .../src/solve/assembly/mod.rs | 134 ++++-------------- .../rustc_trait_selection/src/solve/mod.rs | 8 +- .../traits/next-solver/alias-bound-unsound.rs | 2 +- .../next-solver/alias-bound-unsound.stderr | 14 +- .../ambig-projection-self-is-ambig.rs | 19 +++ ...e_of-tait-in-defining-scope.is_send.stderr | 16 +++ ..._of-tait-in-defining-scope.not_send.stderr | 4 +- .../dont-type_of-tait-in-defining-scope.rs | 3 +- .../recursive-self-normalization-2.rs | 1 + .../recursive-self-normalization-2.stderr | 19 ++- .../overflow/recursive-self-normalization.rs | 1 + .../recursive-self-normalization.stderr | 19 ++- .../issue-76202-trait-impl-for-tait.rs | 22 +-- 13 files changed, 129 insertions(+), 133 deletions(-) create mode 100644 tests/ui/traits/next-solver/assembly/ambig-projection-self-is-ambig.rs create mode 100644 tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index caf9470b4c646..47fc5f007552a 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -271,64 +271,32 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, goal: Goal<'tcx, G>, ) -> Vec> { - debug_assert_eq!(goal, self.resolve_vars_if_possible(goal)); - if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) { - return vec![ambig]; - } - - let mut candidates = self.assemble_candidates_via_self_ty(goal, 0); - - self.assemble_unsize_to_dyn_candidate(goal, &mut candidates); - - self.assemble_blanket_impl_candidates(goal, &mut candidates); - - self.assemble_param_env_candidates(goal, &mut candidates); - - self.assemble_coherence_unknowable_candidates(goal, &mut candidates); - - candidates - } - - /// `?0: Trait` is ambiguous, because it may be satisfied via a builtin rule, - /// object bound, alias bound, etc. We are unable to determine this until we can at - /// least structurally resolve the type one layer. - /// - /// It would also require us to consider all impls of the trait, which is both pretty - /// bad for perf and would also constrain the self type if there is just a single impl. - fn assemble_self_ty_infer_ambiguity_response>( - &mut self, - goal: Goal<'tcx, G>, - ) -> Option> { - if goal.predicate.self_ty().is_ty_var() { - debug!("adding self_ty_infer_ambiguity_response"); + let dummy_candidate = |this: &mut EvalCtxt<'_, 'tcx>, certainty| { let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); - let result = self - .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - .unwrap(); - let mut dummy_probe = self.inspect.new_probe(); + let result = this.evaluate_added_goals_and_make_canonical_response(certainty).unwrap(); + let mut dummy_probe = this.inspect.new_probe(); dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) }); - self.inspect.finish_probe(dummy_probe); - Some(Candidate { source, result }) - } else { - None + this.inspect.finish_probe(dummy_probe); + vec![Candidate { source, result }] + }; + + let Some(normalized_self_ty) = + self.try_normalize_ty(goal.param_env, goal.predicate.self_ty()) + else { + debug!("overflow while evaluating self type"); + return dummy_candidate(self, Certainty::OVERFLOW); + }; + + if normalized_self_ty.is_ty_var() { + debug!("self type has been normalized to infer"); + return dummy_candidate(self, Certainty::AMBIGUOUS); } - } - /// Assemble candidates which apply to the self type. This only looks at candidate which - /// apply to the specific self type and ignores all others. - /// - /// Returns `None` if the self type is still ambiguous. - fn assemble_candidates_via_self_ty>( - &mut self, - goal: Goal<'tcx, G>, - num_steps: usize, - ) -> Vec> { + let goal = + goal.with(self.tcx(), goal.predicate.with_self_ty(self.tcx(), normalized_self_ty)); debug_assert_eq!(goal, self.resolve_vars_if_possible(goal)); - if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) { - return vec![ambig]; - } - let mut candidates = Vec::new(); + let mut candidates = vec![]; self.assemble_non_blanket_impl_candidates(goal, &mut candidates); @@ -338,61 +306,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.assemble_object_bound_candidates(goal, &mut candidates); - self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates, num_steps); - candidates - } + self.assemble_unsize_to_dyn_candidate(goal, &mut candidates); - /// If the self type of a goal is an alias we first try to normalize the self type - /// and compute the candidates for the normalized self type in case that succeeds. - /// - /// These candidates are used in addition to the ones with the alias as a self type. - /// We do this to simplify both builtin candidates and for better performance. - /// - /// We generate the builtin candidates on the fly by looking at the self type, e.g. - /// add `FnPtr` candidates if the self type is a function pointer. Handling builtin - /// candidates while the self type is still an alias seems difficult. This is similar - /// to `try_structurally_resolve_type` during hir typeck (FIXME once implemented). - /// - /// Looking at all impls for some trait goal is prohibitively expensive. We therefore - /// only look at implementations with a matching self type. Because of this function, - /// we can avoid looking at all existing impls if the self type is an alias. - #[instrument(level = "debug", skip_all)] - fn assemble_candidates_after_normalizing_self_ty>( - &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>, - num_steps: usize, - ) { - let tcx = self.tcx(); - let &ty::Alias(_, alias) = goal.predicate.self_ty().kind() else { return }; - - candidates.extend(self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| { - if tcx.recursion_limit().value_within_limit(num_steps) { - let normalized_ty = ecx.next_ty_infer(); - let normalizes_to_goal = - goal.with(tcx, ty::NormalizesTo { alias, term: normalized_ty.into() }); - ecx.add_goal(GoalSource::Misc, normalizes_to_goal); - if let Err(NoSolution) = ecx.try_evaluate_added_goals() { - debug!("self type normalization failed"); - return vec![]; - } - let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty); - debug!(?normalized_ty, "self type normalized"); - // NOTE: Alternatively we could call `evaluate_goal` here and only - // have a `Normalized` candidate. This doesn't work as long as we - // use `CandidateSource` in winnowing. - let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty)); - ecx.assemble_candidates_via_self_ty(goal, num_steps + 1) - } else { - match ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW) { - Ok(result) => vec![Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), - result, - }], - Err(NoSolution) => vec![], - } - } - })); + self.assemble_blanket_impl_candidates(goal, &mut candidates); + + self.assemble_param_env_candidates(goal, &mut candidates); + + self.assemble_coherence_unknowable_candidates(goal, &mut candidates); + + candidates } #[instrument(level = "debug", skip_all)] diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 7c8f885a1f24c..6984f0ba69473 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -288,11 +288,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { /// Normalize a type when it is structually matched on. /// - /// For self types this is generally already handled through - /// `assemble_candidates_after_normalizing_self_ty`, so anything happening - /// in [`EvalCtxt::assemble_candidates_via_self_ty`] does not have to normalize - /// the self type. It is required when structurally matching on any other - /// arguments of a trait goal, e.g. when assembling builtin unsize candidates. + /// In nearly all cases this function must be used before matching on a type. + /// Not doing so is likely to be incomplete and therefore unsound during + /// coherence. #[instrument(level = "debug", skip(self), ret)] fn try_normalize_ty( &mut self, diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index 8fddbd7ecdcc8..633f0e75572c7 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -16,7 +16,7 @@ trait Foo { impl Foo for () { type Item = String where String: Copy; - //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Copy` + //~^ ERROR overflow evaluating the requirement `String: Copy` } fn main() { diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index 874644317ebd3..d5f7e975b1371 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -1,15 +1,17 @@ -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Copy` - --> $DIR/alias-bound-unsound.rs:18:17 +error[E0275]: overflow evaluating the requirement `String: Copy` + --> $DIR/alias-bound-unsound.rs:18:38 | LL | type Item = String where String: Copy; - | ^^^^^^ + | ^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -note: required by a bound in `Foo::Item` - --> $DIR/alias-bound-unsound.rs:8:16 +note: the requirement `String: Copy` appears on the `impl`'s associated type `Item` but not on the corresponding trait's associated type + --> $DIR/alias-bound-unsound.rs:8:10 | +LL | trait Foo { + | --- in this trait LL | type Item: Copy - | ^^^^ required by this bound in `Foo::Item` + | ^^^^ this trait's associated type doesn't have the requirement `String: Copy` error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item` --> $DIR/alias-bound-unsound.rs:24:31 diff --git a/tests/ui/traits/next-solver/assembly/ambig-projection-self-is-ambig.rs b/tests/ui/traits/next-solver/assembly/ambig-projection-self-is-ambig.rs new file mode 100644 index 0000000000000..99a368a746f77 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/ambig-projection-self-is-ambig.rs @@ -0,0 +1,19 @@ +// check-pass +// compile-flags: -Znext-solver + +trait Reader: Default { + fn read_u8_array(&self) -> Result { + todo!() + } + + fn read_u8(&self) -> Result { + let a: [u8; 1] = self.read_u8_array::<_>()?; + // This results in a nested ` as Try>::Residual: Sized` goal. + // The self type normalizes to `?0`. We previously did not force that to be + // ambiguous but instead incompletely applied the `Self: Sized` candidate + // from the `ParamEnv`, resulting in a type error. + Ok(a[0]) + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr new file mode 100644 index 0000000000000..bafc4ba18a7a3 --- /dev/null +++ b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr @@ -0,0 +1,16 @@ +error[E0283]: type annotations needed: cannot satisfy `Foo: Send` + --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18 + | +LL | needs_send::(); + | ^^^ + | + = note: cannot satisfy `Foo: Send` +note: required by a bound in `needs_send` + --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18 + | +LL | fn needs_send() {} + | ^^^^ required by this bound in `needs_send` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr index 076dab29d890b..bafc4ba18a7a3 100644 --- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr +++ b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr @@ -1,12 +1,12 @@ error[E0283]: type annotations needed: cannot satisfy `Foo: Send` - --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18 + --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18 | LL | needs_send::(); | ^^^ | = note: cannot satisfy `Foo: Send` note: required by a bound in `needs_send` - --> $DIR/dont-type_of-tait-in-defining-scope.rs:13:18 + --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18 | LL | fn needs_send() {} | ^^^^ required by this bound in `needs_send` diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs index a1f38e69e53ef..ef0360248b59a 100644 --- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs +++ b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs @@ -1,6 +1,5 @@ // revisions: is_send not_send // compile-flags: -Znext-solver -//[is_send] check-pass #![feature(type_alias_impl_trait)] @@ -14,7 +13,7 @@ fn needs_send() {} fn test(_: Foo) { needs_send::(); - //[not_send]~^ ERROR type annotations needed: cannot satisfy `Foo: Send` + //~^ ERROR type annotations needed: cannot satisfy `Foo: Send` } fn defines(_: Foo) { diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index 932826519b7d2..983a0fec65349 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -17,6 +17,7 @@ fn test::Assoc2> + Foo2::Assoc //~| ERROR overflow evaluating the requirement `::Assoc1 == _` //~| ERROR overflow evaluating the requirement `::Assoc1 == _` //~| ERROR overflow evaluating the requirement `::Assoc1 == _` + //~| ERROR overflow evaluating the requirement `::Assoc1: Sized` //~| ERROR overflow evaluating the requirement `::Assoc1: Bar` } 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 e4f1f9cf02255..ed87404d57395 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 @@ -19,6 +19,23 @@ note: required by a bound in `needs_bar` LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` +error[E0275]: overflow evaluating the requirement `::Assoc1: Sized` + --> $DIR/recursive-self-normalization-2.rs:15:17 + | +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` + --> $DIR/recursive-self-normalization-2.rs:12:14 + | +LL | fn needs_bar() {} + | ^ required by this bound in `needs_bar` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn needs_bar() {} + | ++++++++ + error[E0275]: overflow evaluating the requirement `::Assoc1 == _` --> $DIR/recursive-self-normalization-2.rs:15:5 | @@ -45,6 +62,6 @@ LL | needs_bar::(); = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`) = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs index 32672c08c7e07..40e2aa9e63f31 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs @@ -13,6 +13,7 @@ fn test::Assoc>>() { //~| ERROR overflow evaluating the requirement `::Assoc == _` //~| ERROR overflow evaluating the requirement `::Assoc == _` //~| ERROR overflow evaluating the requirement `::Assoc == _` + //~| ERROR overflow evaluating the requirement `::Assoc: Sized` //~| ERROR overflow evaluating the requirement `::Assoc: 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 da5c8bde568d2..e4ef2f60740f4 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr @@ -19,6 +19,23 @@ note: required by a bound in `needs_bar` LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` +error[E0275]: overflow evaluating the requirement `::Assoc: Sized` + --> $DIR/recursive-self-normalization.rs:11:17 + | +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` + --> $DIR/recursive-self-normalization.rs:8:14 + | +LL | fn needs_bar() {} + | ^ required by this bound in `needs_bar` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn needs_bar() {} + | ++++++++ + error[E0275]: overflow evaluating the requirement `::Assoc == _` --> $DIR/recursive-self-normalization.rs:11:5 | @@ -45,6 +62,6 @@ LL | needs_bar::(); = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`) = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs index af1c18bbb59c8..b6906f68ded57 100644 --- a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs +++ b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs @@ -4,20 +4,14 @@ // revisions: current next //[next] compile-flags: -Znext-solver // check-pass - #![feature(type_alias_impl_trait)] -trait Dummy {} -impl Dummy for () {} - -type F = impl Dummy; -fn f() -> F {} - trait Test { fn test(self); } -impl Test for F { + +impl Test for define::F { fn test(self) {} } @@ -27,7 +21,17 @@ impl Test for i32 { fn test(self) {} } +mod define { + use super::*; + + pub trait Dummy {} + impl Dummy for () {} + + pub type F = impl Dummy; + pub fn f() -> F {} +} + fn main() { - let x: F = f(); + let x = define::f(); x.test(); } From ea4e5b8458f80690ee548008350b0c7533b65c62 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 8 Jan 2024 15:38:01 +0100 Subject: [PATCH 355/676] merge builtin unsize candidates again --- .../src/solve/assembly/mod.rs | 31 ------- .../src/solve/normalizes_to/mod.rs | 7 -- .../src/solve/trait_goals.rs | 90 +++++++++---------- 3 files changed, 41 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 47fc5f007552a..915d722dd0206 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -253,17 +253,6 @@ pub(super) trait GoalKind<'tcx>: ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)>; - - /// Consider the `Unsize` candidate corresponding to coercing a sized type - /// into a `dyn Trait`. - /// - /// This is computed separately from the rest of the `Unsize` candidates - /// since it is only done once per self type, and not once per - /// *normalization step* (in `assemble_candidates_via_self_ty`). - fn consider_unsize_to_dyn_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, - goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; } impl<'tcx> EvalCtxt<'_, 'tcx> { @@ -306,8 +295,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.assemble_object_bound_candidates(goal, &mut candidates); - self.assemble_unsize_to_dyn_candidate(goal, &mut candidates); - self.assemble_blanket_impl_candidates(goal, &mut candidates); self.assemble_param_env_candidates(goal, &mut candidates); @@ -422,24 +409,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - #[instrument(level = "debug", skip_all)] - fn assemble_unsize_to_dyn_candidate>( - &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>, - ) { - let tcx = self.tcx(); - if tcx.lang_items().unsize_trait() == Some(goal.predicate.trait_def_id(tcx)) { - match G::consider_unsize_to_dyn_candidate(self, goal) { - Ok(result) => candidates.push(Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), - result, - }), - Err(NoSolution) => (), - } - } - } - #[instrument(level = "debug", skip_all)] fn assemble_blanket_impl_candidates>( &mut self, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index ccee6f8eb29b9..9f1b4a09a20ba 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -603,13 +603,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ) } - fn consider_unsize_to_dyn_candidate( - _ecx: &mut EvalCtxt<'_, 'tcx>, - goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { - bug!("`Unsize` does not have an associated type: {:?}", goal) - } - fn consider_structural_builtin_unsize_candidates( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index be07927568446..b185e4e5f8eb0 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -490,53 +490,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx.evaluate_added_goals_and_make_canonical_response(certainty) } - fn consider_unsize_to_dyn_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, - goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { - ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(|ecx| { - let a_ty = goal.predicate.self_ty(); - // We need to normalize the b_ty since it's destructured as a `dyn Trait`. - let Some(b_ty) = - ecx.try_normalize_ty(goal.param_env, goal.predicate.trait_ref.args.type_at(1)) - else { - return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW); - }; - - let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { - return Err(NoSolution); - }; - - let tcx = ecx.tcx(); - - // Can only unsize to an object-safe trait. - if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) { - return Err(NoSolution); - } - - // Check that the type implements all of the predicates of the trait object. - // (i.e. the principal, all of the associated types match, and any auto traits) - ecx.add_goals( - GoalSource::ImplWhereBound, - b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), - ); - - // The type must be `Sized` to be unsized. - if let Some(sized_def_id) = tcx.lang_items().sized_trait() { - ecx.add_goal( - GoalSource::ImplWhereBound, - goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])), - ); - } else { - return Err(NoSolution); - } - - // The type must outlive the lifetime of the `dyn` we're unsizing into. - ecx.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region))); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) - } - /// ```ignore (builtin impl example) /// trait Trait { /// fn foo(&self); @@ -588,8 +541,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { goal, a_data, a_region, b_data, b_region, ), - // `T` -> `dyn Trait` unsizing is handled separately in `consider_unsize_to_dyn_candidate` - (_, &ty::Dynamic(..)) => vec![], + // `T` -> `dyn Trait` unsizing. + (_, &ty::Dynamic(b_region, b_data, ty::Dyn)) => result_to_single( + ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data), + BuiltinImplSource::Misc, + ), // `[T; N]` -> `[T]` unsizing (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => result_to_single( @@ -691,6 +647,42 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { responses } + fn consider_builtin_unsize_to_dyn_candidate( + &mut self, + goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, + b_data: &'tcx ty::List>, + b_region: ty::Region<'tcx>, + ) -> QueryResult<'tcx> { + let tcx = self.tcx(); + let Goal { predicate: (a_ty, _), .. } = goal; + + // Can only unsize to an object-safe trait. + if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) { + return Err(NoSolution); + } + + // Check that the type implements all of the predicates of the trait object. + // (i.e. the principal, all of the associated types match, and any auto traits) + self.add_goals( + GoalSource::ImplWhereBound, + b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), + ); + + // The type must be `Sized` to be unsized. + if let Some(sized_def_id) = tcx.lang_items().sized_trait() { + self.add_goal( + GoalSource::ImplWhereBound, + goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])), + ); + } else { + return Err(NoSolution); + } + + // The type must outlive the lifetime of the `dyn` we're unsizing into. + self.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region))); + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + fn consider_builtin_upcast_to_principal( &mut self, goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, From 503342f51c26b8c5efcf3f3c97818c232d988c41 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 29 Jan 2024 12:00:29 -0500 Subject: [PATCH 356/676] Update books --- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/edition-guide b/src/doc/edition-guide index bbffb074e16be..baafacc6d8701 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit bbffb074e16bef89772818b400b6c76a65eac126 +Subproject commit baafacc6d8701269dab1e1e333f3547fb54b5a59 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 3f9df2b9885c6..2e95fc2fd31d6 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 3f9df2b9885c6741365da2e12ed6662cd0e827d6 +Subproject commit 2e95fc2fd31d669947e993aa07ef10dc9828bee7 diff --git a/src/doc/reference b/src/doc/reference index 8c77e8be9da1a..a0b119535e774 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 8c77e8be9da1a9c70545556218d563c8d061f1fd +Subproject commit a0b119535e7740f68494c4f0582f7ad008b00ccd diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index ddf5cb0e6ee54..179256a445d61 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit ddf5cb0e6ee54ba2dd84c8ca3e1314120014e20d +Subproject commit 179256a445d6144f5f371fdefb993f48f33978b0 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 4af29d1a7f64f..ec287e3327776 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 4af29d1a7f64f88a36539662c6a84fe1fbe6cde1 +Subproject commit ec287e332777627185be4798ad22599ffe7b84aa From 1df1ebf6add883bcd620c607da40cda3b0fcfc3d Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 27 Jan 2024 17:24:45 +0100 Subject: [PATCH 357/676] std: always check the result of `pthread_mutex_lock` --- .../src/sys/pal/unix/locks/pthread_mutex.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/locks/pthread_mutex.rs b/library/std/src/sys/pal/unix/locks/pthread_mutex.rs index 8a78bc1fd7399..ee0794334fbe3 100644 --- a/library/std/src/sys/pal/unix/locks/pthread_mutex.rs +++ b/library/std/src/sys/pal/unix/locks/pthread_mutex.rs @@ -1,4 +1,5 @@ use crate::cell::UnsafeCell; +use crate::io::Error; use crate::mem::{forget, MaybeUninit}; use crate::sys::cvt_nz; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; @@ -103,8 +104,24 @@ impl Mutex { #[inline] pub unsafe fn lock(&self) { + #[cold] + #[inline(never)] + fn fail(r: i32) -> ! { + let error = Error::from_raw_os_error(r); + panic!("failed to lock mutex: {error}"); + } + let r = libc::pthread_mutex_lock(raw(self)); - debug_assert_eq!(r, 0); + // As we set the mutex type to `PTHREAD_MUTEX_NORMAL` above, we expect + // the lock call to never fail. Unfortunately however, some platforms + // (Solaris) do not conform to the standard, and instead always provide + // deadlock detection. How kind of them! Unfortunately that means that + // we need to check the error code here. To save us from UB on other + // less well-behaved platforms in the future, we do it even on "good" + // platforms like macOS. See #120147 for more context. + if r != 0 { + fail(r) + } } #[inline] From 32a0afe30c26044a62d098910464989258f0bc2e Mon Sep 17 00:00:00 2001 From: Chad Norvell Date: Mon, 22 Jan 2024 20:42:27 +0000 Subject: [PATCH 358/676] rustdoc: Prevent JS injection from localStorage --- src/librustdoc/html/static/js/storage.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index ac9c6f377b82a..bda7b3c647e7e 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -101,6 +101,14 @@ const getVar = (function getVar(name) { }); function switchTheme(newThemeName, saveTheme) { + const themeNames = getVar("themes").split(",").filter(t => t); + themeNames.push(...builtinThemes); + + // Ensure that the new theme name is among the defined themes + if (themeNames.indexOf(newThemeName) === -1) { + return; + } + // If this new value comes from a system setting or from the previously // saved theme, no need to save it. if (saveTheme) { @@ -115,7 +123,7 @@ function switchTheme(newThemeName, saveTheme) { window.currentTheme = null; } } else { - const newHref = getVar("root-path") + newThemeName + + const newHref = getVar("root-path") + encodeURIComponent(newThemeName) + getVar("resource-suffix") + ".css"; if (!window.currentTheme) { // If we're in the middle of loading, document.write blocks From 09f16b596dce8f584ac070127a07f8fc6775ab30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 23 Jan 2024 18:24:40 +0000 Subject: [PATCH 359/676] Avoid ICE in trait without `dyn` lint Do not attempt to provide an accurate suggestion for `impl Trait` in bare trait types when linting. Instead, only do the object safety check when an E0782 is already going to be emitted in the 2021 edition. Fix #120241. --- .../rustc_hir_analysis/src/astconv/lint.rs | 8 +- .../avoid-ice-on-warning-2.new.stderr | 12 +++ ...derr => avoid-ice-on-warning-2.old.stderr} | 28 ++----- .../object-safety/avoid-ice-on-warning-2.rs | 13 +-- .../avoid-ice-on-warning-3.new.stderr | 47 +++++++++++ ...derr => avoid-ice-on-warning-3.old.stderr} | 84 +++++++------------ .../object-safety/avoid-ice-on-warning-3.rs | 31 +++---- .../avoid-ice-on-warning.new.stderr | 15 ++++ ...stderr => avoid-ice-on-warning.old.stderr} | 12 +-- .../ui/object-safety/avoid-ice-on-warning.rs | 7 +- .../bare-trait-dont-suggest-dyn.fixed | 9 -- .../bare-trait-dont-suggest-dyn.new.fixed | 16 ++++ ...=> bare-trait-dont-suggest-dyn.new.stderr} | 2 +- .../bare-trait-dont-suggest-dyn.old.stderr | 39 +++++++++ .../bare-trait-dont-suggest-dyn.rs | 9 +- .../ui/traits/bound/not-on-bare-trait.stderr | 14 +--- 16 files changed, 221 insertions(+), 125 deletions(-) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr rename tests/ui/object-safety/{avoid-ice-on-warning-2.stderr => avoid-ice-on-warning-2.old.stderr} (60%) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr rename tests/ui/object-safety/{avoid-ice-on-warning-3.stderr => avoid-ice-on-warning-3.old.stderr} (63%) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning.new.stderr rename tests/ui/object-safety/{avoid-ice-on-warning.stderr => avoid-ice-on-warning.old.stderr} (71%) delete mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed create mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed rename tests/ui/object-safety/{bare-trait-dont-suggest-dyn.stderr => bare-trait-dont-suggest-dyn.new.stderr} (95%) create mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 98cd8a085baef..a6ac8ecd950ea 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -132,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ], Applicability::MachineApplicable, ); - } else if diag.is_error() && is_downgradable { + } else if is_downgradable { // We'll emit the object safety error already, with a structured suggestion. diag.downgrade_to_delayed_bug(); } @@ -158,7 +158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if !is_object_safe { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); - if diag.is_error() && is_downgradable { + if is_downgradable { // We'll emit the object safety error already, with a structured suggestion. diag.downgrade_to_delayed_bug(); } @@ -241,9 +241,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { let msg = "trait objects without an explicit `dyn` are deprecated"; tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| { - if self_ty.span.can_be_used_for_suggestions() - && !self.maybe_lint_impl_trait(self_ty, lint) - { + if self_ty.span.can_be_used_for_suggestions() { lint.multipart_suggestion_verbose( "use `dyn`", sugg, diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr new file mode 100644 index 0000000000000..7aec3a73fe964 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr @@ -0,0 +1,12 @@ +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/avoid-ice-on-warning-2.rs:4:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = 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 + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr similarity index 60% rename from tests/ui/object-safety/avoid-ice-on-warning-2.stderr rename to tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr index 2755eee6f3529..41c09b7df6289 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr @@ -1,43 +1,33 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-2.rs:1:13 + --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id(f: Copy) -> usize { | ^^^^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see - = note: `Copy` it is not object safe, so it can't be `dyn` = note: `#[warn(bare_trait_objects)]` on by default -help: use a new generic type parameter, constrained by `Copy` +help: use `dyn` | -LL | fn id(f: T) -> usize { - | +++++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn id(f: impl Copy) -> usize { - | ++++ +LL | fn id(f: dyn Copy) -> usize { + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-2.rs:1:13 + --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id(f: Copy) -> usize { | ^^^^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see - = note: `Copy` it is not object safe, so it can't be `dyn` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use a new generic type parameter, constrained by `Copy` - | -LL | fn id(f: T) -> usize { - | +++++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | fn id(f: impl Copy) -> usize { - | ++++ +LL | fn id(f: dyn Copy) -> usize { + | +++ error[E0038]: the trait `Copy` cannot be made into an object - --> $DIR/avoid-ice-on-warning-2.rs:1:13 + --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id(f: Copy) -> usize { | ^^^^ `Copy` cannot be made into an object diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/object-safety/avoid-ice-on-warning-2.rs index cd34362d3dd52..9a6a4378fa383 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.rs @@ -1,9 +1,12 @@ +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 fn id(f: Copy) -> usize { -//~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -//~| ERROR the trait `Copy` cannot be made into an object +//~^ ERROR the trait `Copy` cannot be made into an object +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! f() } fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr new file mode 100644 index 0000000000000..fd92d43ef9a24 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr @@ -0,0 +1,47 @@ +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:4:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ `A` 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 + --> $DIR/avoid-ice-on-warning-3.rs:12:14 + | +LL | trait A { fn g(b: B) -> B; } + | - ^ ...because associated function `g` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `g` into a method by giving it a `&self` argument + | +LL | trait A { fn g(&self, b: B) -> B; } + | ++++++ +help: alternatively, consider constraining `g` so it does not apply to trait objects + | +LL | trait A { fn g(b: B) -> B where Self: Sized; } + | +++++++++++++++++ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:12:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ `B` 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 + --> $DIR/avoid-ice-on-warning-3.rs:4:14 + | +LL | trait B { fn f(a: A) -> A; } + | - ^ ...because associated function `f` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | trait B { fn f(&self, a: A) -> A; } + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | trait B { fn f(a: A) -> A where Self: Sized; } + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr similarity index 63% rename from tests/ui/object-safety/avoid-ice-on-warning-3.stderr rename to tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr index 0fc67770b96dd..a36e2519c804d 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr @@ -1,93 +1,78 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:9:19 + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | -LL | trait A { fn g(b: B) -> B; } +LL | trait B { fn f(a: A) -> A; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see - = note: `B` it is not object safe, so it can't be `dyn` = note: `#[warn(bare_trait_objects)]` on by default -help: use a new generic type parameter, constrained by `B` - | -LL | trait A { fn g(b: T) -> B; } - | ++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | trait A { fn g(b: impl B) -> B; } - | ++++ +LL | trait B { fn f(a: dyn A) -> A; } + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:9:25 + --> $DIR/avoid-ice-on-warning-3.rs:4:25 | -LL | trait A { fn g(b: B) -> B; } +LL | trait B { fn f(a: A) -> A; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type +help: use `dyn` | -LL | trait A { fn g(b: B) -> impl B; } - | ++++ +LL | trait B { fn f(a: A) -> dyn A; } + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:1:19 + --> $DIR/avoid-ice-on-warning-3.rs:12:19 | -LL | trait B { fn f(a: A) -> A; } +LL | trait A { fn g(b: B) -> B; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see - = note: `A` it is not object safe, so it can't be `dyn` -help: use a new generic type parameter, constrained by `A` - | -LL | trait B { fn f(a: T) -> A; } - | ++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | trait B { fn f(a: impl A) -> A; } - | ++++ +LL | trait A { fn g(b: dyn B) -> B; } + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:1:25 + --> $DIR/avoid-ice-on-warning-3.rs:12:25 | -LL | trait B { fn f(a: A) -> A; } +LL | trait A { fn g(b: B) -> B; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type +help: use `dyn` | -LL | trait B { fn f(a: A) -> impl A; } - | ++++ +LL | trait A { fn g(b: B) -> dyn B; } + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:1:19 + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | LL | trait B { fn f(a: A) -> A; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see - = note: `A` it is not object safe, so it can't be `dyn` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use a new generic type parameter, constrained by `A` - | -LL | trait B { fn f(a: T) -> A; } - | ++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | trait B { fn f(a: impl A) -> A; } - | ++++ +LL | trait B { fn f(a: dyn A) -> A; } + | +++ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:1:19 + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | LL | trait B { fn f(a: A) -> A; } | ^ `A` 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 - --> $DIR/avoid-ice-on-warning-3.rs:9:14 + --> $DIR/avoid-ice-on-warning-3.rs:12:14 | LL | trait A { fn g(b: B) -> B; } | - ^ ...because associated function `g` has no `self` parameter @@ -103,32 +88,27 @@ LL | trait A { fn g(b: B) -> B where Self: Sized; } | +++++++++++++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:9:19 + --> $DIR/avoid-ice-on-warning-3.rs:12:19 | LL | trait A { fn g(b: B) -> B; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see - = note: `B` it is not object safe, so it can't be `dyn` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use a new generic type parameter, constrained by `B` - | -LL | trait A { fn g(b: T) -> B; } - | ++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | trait A { fn g(b: impl B) -> B; } - | ++++ +LL | trait A { fn g(b: dyn B) -> B; } + | +++ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:9:19 + --> $DIR/avoid-ice-on-warning-3.rs:12:19 | LL | trait A { fn g(b: B) -> B; } | ^ `B` 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 - --> $DIR/avoid-ice-on-warning-3.rs:1:14 + --> $DIR/avoid-ice-on-warning-3.rs:4:14 | LL | trait B { fn f(a: A) -> A; } | - ^ ...because associated function `f` has no `self` parameter diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/object-safety/avoid-ice-on-warning-3.rs index caaf4d0fd99aa..40563e233dec6 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.rs @@ -1,17 +1,20 @@ +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 trait B { fn f(a: A) -> A; } -//~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN this is accepted in the current edition -//~| WARN this is accepted in the current edition -//~| ERROR the trait `A` cannot be made into an object +//~^ ERROR the trait `A` cannot be made into an object +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition +//[old]~| WARN this is accepted in the current edition +//[old]~| WARN this is accepted in the current edition trait A { fn g(b: B) -> B; } -//~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN this is accepted in the current edition -//~| WARN this is accepted in the current edition -//~| ERROR the trait `B` cannot be made into an object +//~^ ERROR the trait `B` cannot be made into an object +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition +//[old]~| WARN this is accepted in the current edition +//[old]~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning.new.stderr new file mode 100644 index 0000000000000..517f910080de7 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.new.stderr @@ -0,0 +1,15 @@ +error: return types are denoted using `->` + --> $DIR/avoid-ice-on-warning.rs:4:23 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^ help: use `->` instead + +error[E0405]: cannot find trait `call_that` in this scope + --> $DIR/avoid-ice-on-warning.rs:4:36 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning.stderr b/tests/ui/object-safety/avoid-ice-on-warning.old.stderr similarity index 71% rename from tests/ui/object-safety/avoid-ice-on-warning.stderr rename to tests/ui/object-safety/avoid-ice-on-warning.old.stderr index 1046f177e8296..7c7af9682800f 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning.old.stderr @@ -1,17 +1,17 @@ error: return types are denoted using `->` - --> $DIR/avoid-ice-on-warning.rs:1:23 + --> $DIR/avoid-ice-on-warning.rs:4:23 | LL | fn call_this(f: F) : Fn(&str) + call_that {} | ^ help: use `->` instead error[E0405]: cannot find trait `call_that` in this scope - --> $DIR/avoid-ice-on-warning.rs:1:36 + --> $DIR/avoid-ice-on-warning.rs:4:36 | LL | fn call_this(f: F) : Fn(&str) + call_that {} | ^^^^^^^^^ not found in this scope warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning.rs:1:25 + --> $DIR/avoid-ice-on-warning.rs:4:25 | LL | fn call_this(f: F) : Fn(&str) + call_that {} | ^^^^^^^^^^^^^^^^^^^^ @@ -19,10 +19,10 @@ LL | fn call_this(f: F) : Fn(&str) + call_that {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: `Fn(&str) + call_that` is not object safe, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type +help: use `dyn` | -LL | fn call_this(f: F) : impl Fn(&str) + call_that {} - | ++++ +LL | fn call_this(f: F) : dyn Fn(&str) + call_that {} + | +++ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/object-safety/avoid-ice-on-warning.rs index d2a1eeb5286b0..5192da94216e1 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning.rs @@ -1,6 +1,9 @@ +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 fn call_this(f: F) : Fn(&str) + call_that {} //~^ ERROR return types are denoted using `->` //~| ERROR cannot find trait `call_that` in this scope -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! fn main() {} diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed deleted file mode 100644 index e95b982966d0b..0000000000000 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed +++ /dev/null @@ -1,9 +0,0 @@ -// run-rustfix -#![deny(bare_trait_objects)] -fn ord_prefer_dot(s: String) -> impl Ord { - //~^ ERROR the trait `Ord` cannot be made into an object - (s.starts_with("."), s) -} -fn main() { - let _ = ord_prefer_dot(String::new()); -} diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed new file mode 100644 index 0000000000000..301c36c619139 --- /dev/null +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed @@ -0,0 +1,16 @@ +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 +//[new] run-rustfix +// FIXME: the test suite tries to create a crate called `bare_trait_dont_suggest_dyn.new` +#![crate_name="bare_trait_dont_suggest_dyn"] +#![deny(bare_trait_objects)] +fn ord_prefer_dot(s: String) -> impl Ord { + //~^ ERROR the trait `Ord` cannot be made into an object + //[old]~| ERROR trait objects without an explicit `dyn` are deprecated + //[old]~| WARNING this is accepted in the current edition (Rust 2015) + (s.starts_with("."), s) +} +fn main() { + let _ = ord_prefer_dot(String::new()); +} diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr similarity index 95% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr rename to tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr index 2c499d240ab0b..52db31d620c3d 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Ord` cannot be made into an object - --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33 + --> $DIR/bare-trait-dont-suggest-dyn.rs:8:33 | LL | fn ord_prefer_dot(s: String) -> Ord { | ^^^ `Ord` cannot be made into an object diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr new file mode 100644 index 0000000000000..274d5a639a43b --- /dev/null +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr @@ -0,0 +1,39 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-dont-suggest-dyn.rs:8:33 + | +LL | fn ord_prefer_dot(s: String) -> Ord { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/bare-trait-dont-suggest-dyn.rs:7:9 + | +LL | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ +help: use `dyn` + | +LL | fn ord_prefer_dot(s: String) -> dyn Ord { + | +++ + +error[E0038]: the trait `Ord` cannot be made into an object + --> $DIR/bare-trait-dont-suggest-dyn.rs:8:33 + | +LL | fn ord_prefer_dot(s: String) -> Ord { + | ^^^ `Ord` 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/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter + ::: $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter +help: consider using an opaque type instead + | +LL | fn ord_prefer_dot(s: String) -> impl Ord { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs index fdf7e0a77aa34..64586b77b8c2b 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs @@ -1,7 +1,14 @@ -// run-rustfix +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 +//[new] run-rustfix +// FIXME: the test suite tries to create a crate called `bare_trait_dont_suggest_dyn.new` +#![crate_name="bare_trait_dont_suggest_dyn"] #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { //~^ ERROR the trait `Ord` cannot be made into an object + //[old]~| ERROR trait objects without an explicit `dyn` are deprecated + //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) } fn main() { diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index 8d0e40be788c1..6d56851bf3495 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -7,18 +7,10 @@ LL | fn foo(_x: Foo + Send) { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use a new generic type parameter, constrained by `Foo + Send` +help: use `dyn` | -LL | fn foo(_x: T) { - | +++++++++++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn foo(_x: impl Foo + Send) { - | ++++ -help: alternatively, use a trait object to accept any type that implements `Foo + Send`, accessing its methods at runtime using dynamic dispatch - | -LL | fn foo(_x: &(dyn Foo + Send)) { - | +++++ + +LL | fn foo(_x: dyn Foo + Send) { + | +++ error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time --> $DIR/not-on-bare-trait.rs:7:8 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 360/676] 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 361/676] 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 362/676] 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 6468d44c37b62786cf84b977ef031758d4d2d27f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 29 Jan 2024 20:32:27 +0100 Subject: [PATCH 363/676] Improve error message when `cargo build` is used to build the compiler --- compiler/rustc_macros/build.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 compiler/rustc_macros/build.rs diff --git a/compiler/rustc_macros/build.rs b/compiler/rustc_macros/build.rs new file mode 100644 index 0000000000000..717f8a922457d --- /dev/null +++ b/compiler/rustc_macros/build.rs @@ -0,0 +1,16 @@ +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); + if !std::env::var("RUSTC_BOOTSTRAP").is_ok() { + eprintln!( + "error: you are attempting to build the compiler without going through bootstrap" + ); + eprintln!( + "help: see https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html for how to build the compiler" + ); + eprintln!( + "help: if you know what you're doing, set the RUSTC_BOOTSTRAP environment variable to any value" + ); + panic!("wrong command used for building"); + } +} 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 364/676] 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 96e6cfa34a38cf7ef51aad168afa9b1e628cf26f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Jan 2024 20:40:22 +0100 Subject: [PATCH 365/676] Improve display of crate name when hovered --- src/librustdoc/html/static/css/rustdoc.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 9c593aa85d987..c01a25534f9f9 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -638,7 +638,7 @@ ul.block, .block li { .sidebar-crate h2 a { display: block; - margin: 0 calc(-24px + 0.25rem) 0 -0.5rem; + margin: 0 calc(-24px + 0.25rem) 0 -0.2rem; /* Align the sidebar crate link with the search bar, which have different font sizes. @@ -653,7 +653,7 @@ ul.block, .block li { x = ( 16px - 0.57rem ) / 2 */ padding: calc( ( 16px - 0.57rem ) / 2 ) 0.25rem; - padding-left: 0.5rem; + padding-left: 0.2rem; } .sidebar-crate h2 .version { @@ -661,8 +661,6 @@ ul.block, .block li { font-weight: normal; font-size: 1rem; overflow-wrap: break-word; - /* opposite of the link padding, cut in half again */ - margin-top: calc( ( -16px + 0.57rem ) / 2 ); } .sidebar-crate + .version { From b4efe07006773c3049fb78586fd00acff690e544 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 29 Jan 2024 19:31:29 +0000 Subject: [PATCH 366/676] Remove some unnecessary check logic for lang items in HIR typeck --- compiler/rustc_hir_typeck/messages.ftl | 5 -- compiler/rustc_hir_typeck/src/callee.rs | 25 +++------- compiler/rustc_hir_typeck/src/check.rs | 16 ++---- compiler/rustc_hir_typeck/src/errors.rs | 16 ------ compiler/rustc_hir_typeck/src/lib.rs | 9 ---- compiler/rustc_hir_typeck/src/method/mod.rs | 21 ++------ compiler/rustc_hir_typeck/src/op.rs | 21 +------- compiler/rustc_hir_typeck/src/place_op.rs | 30 +----------- tests/ui/lang-items/bad-add-impl.rs | 18 ------- tests/ui/lang-items/bad-add-impl.stderr | 11 ----- .../fn-fn_mut-call-ill-formed.bad_item.stderr | 18 ------- .../fn-fn_mut-call-ill-formed.bad_sig.stderr | 18 ------- ...-fn_mut-call-ill-formed.fn_bad_item.stderr | 18 ------- ...n-fn_mut-call-ill-formed.fn_bad_sig.stderr | 18 ------- ...mut-call-ill-formed.fn_mut_bad_item.stderr | 18 ------- ..._mut-call-ill-formed.fn_mut_bad_sig.stderr | 18 ------- ...ut-call-ill-formed.fn_once_bad_item.stderr | 18 ------- ...mut-call-ill-formed.fn_once_bad_sig.stderr | 18 ------- .../lang-items/fn-fn_mut-call-ill-formed.rs | 49 ------------------- tests/ui/lang-items/issue-31076.rs | 17 ------- tests/ui/lang-items/issue-31076.stderr | 19 ------- tests/ui/lang-items/issue-86238.rs | 16 ------ tests/ui/lang-items/issue-86238.stderr | 10 ---- .../panic-handler-requires-panic-info.rs | 2 +- .../panic-handler-requires-panic-info.stderr | 6 ++- tests/ui/traits/invalid_operator_trait.rs | 23 --------- tests/ui/traits/invalid_operator_trait.stderr | 8 --- 27 files changed, 21 insertions(+), 445 deletions(-) delete mode 100644 tests/ui/lang-items/bad-add-impl.rs delete mode 100644 tests/ui/lang-items/bad-add-impl.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr delete mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs delete mode 100644 tests/ui/lang-items/issue-31076.rs delete mode 100644 tests/ui/lang-items/issue-31076.stderr delete mode 100644 tests/ui/lang-items/issue-86238.rs delete mode 100644 tests/ui/lang-items/issue-86238.stderr delete mode 100644 tests/ui/traits/invalid_operator_trait.rs delete mode 100644 tests/ui/traits/invalid_operator_trait.stderr diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 4fd9391acc368..220da19a29dc8 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -96,9 +96,6 @@ hir_typeck_lossy_provenance_ptr2int = hir_typeck_method_call_on_unknown_raw_pointee = cannot call a method on a raw pointer with an unknown pointee type -hir_typeck_missing_fn_lang_items = failed to find an overloaded call trait for closure call - .help = make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}` hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method -> @@ -108,8 +105,6 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for { hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide -hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters - hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}` hir_typeck_option_result_cloned = use `{$def_path}::cloned` to clone the value inside the `{$def_path}` hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value inside the `{$def_path}` diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 9dc365526d467..995d4a97bd518 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -253,28 +253,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adjusted_ty, opt_input_type.as_ref().map(slice::from_ref), ) { - // Check for `self` receiver on the method, otherwise we can't use this as a `Fn*` trait. - if !self.tcx.associated_item(ok.value.def_id).fn_has_self_parameter { - self.dcx().span_delayed_bug( - call_expr.span, - "input to overloaded call fn is not a self receiver", - ); - return None; - } - let method = self.register_infer_ok_obligations(ok); let mut autoref = None; if borrow { // Check for &self vs &mut self in the method signature. Since this is either // the Fn or FnMut trait, it should be one of those. let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else { - // The `fn`/`fn_mut` lang item is ill-formed, which should have - // caused an error elsewhere. - self.dcx().span_delayed_bug( - call_expr.span, - "input to call/call_mut is not a ref", - ); - return None; + bug!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut") }; // For initial two-phase borrow @@ -948,9 +933,11 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { ); } None => { - // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once` - // lang items are not defined (issue #86238). - fcx.dcx().emit_err(errors::MissingFnLangItems { span: self.call_expr.span }); + span_bug!( + self.call_expr.span, + "Expected to find a suitable `Fn`/`FnMut`/`FnOnce` implementation for `{}`", + self.adjusted_ty + ) } } } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index ec63954df3461..aab78465f8c85 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -152,26 +152,22 @@ pub(super) fn check_fn<'a, 'tcx>( } fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>) { + let span = tcx.def_span(fn_id); + let DefKind::Fn = tcx.def_kind(fn_id) else { - let span = tcx.def_span(fn_id); tcx.dcx().span_err(span, "should be a function"); return; }; let generic_counts = tcx.generics_of(fn_id).own_counts(); if generic_counts.types != 0 { - let span = tcx.def_span(fn_id); tcx.dcx().span_err(span, "should have no type parameters"); } if generic_counts.consts != 0 { - let span = tcx.def_span(fn_id); tcx.dcx().span_err(span, "should have no const parameters"); } - let Some(panic_info_did) = tcx.lang_items().panic_info() else { - tcx.dcx().err("language item required, but not found: `panic_info`"); - return; - }; + let panic_info_did = tcx.require_lang_item(hir::LangItem::PanicInfo, Some(span)); // build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !` let panic_info_ty = tcx.type_of(panic_info_did).instantiate( @@ -203,11 +199,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> let _ = check_function_signature( tcx, - ObligationCause::new( - tcx.def_span(fn_id), - fn_id, - ObligationCauseCode::LangFunctionType(sym::panic_impl), - ), + ObligationCause::new(span, fn_id, ObligationCauseCode::LangFunctionType(sym::panic_impl)), fn_id.into(), expected_sig, ); diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index b75cf4b4e8bca..40fffbe6ba5bd 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -83,14 +83,6 @@ pub struct MethodCallOnUnknownRawPointee { pub span: Span, } -#[derive(Diagnostic)] -#[diag(hir_typeck_missing_fn_lang_items)] -#[help] -pub struct MissingFnLangItems { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)] pub struct FunctionalRecordUpdateOnNonStruct { @@ -193,14 +185,6 @@ pub struct AddMissingParenthesesInRange { pub right: Span, } -#[derive(Diagnostic)] -#[diag(hir_typeck_op_trait_generic_params)] -pub struct OpMethodGenericParams { - #[primary_span] - pub span: Span, - pub method_name: String, -} - pub struct TypeMismatchFruTypo { /// Span of the LHS of the range pub expr_span: Span, diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 36aa949668ff3..deb3ad2edc740 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -444,15 +444,6 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! { diag.emit() } -/// `expected` here is the expected number of explicit generic arguments on the trait. -fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool { - let generics = tcx.generics_of(trait_did); - generics.count() - == expected - + if generics.has_self { 1 } else { 0 } - + if generics.host_effect_index.is_some() { 1 } else { 0 } -} - pub fn provide(providers: &mut Providers) { method::provide(providers); *providers = Providers { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index af172b59a1467..804d6ff2cb577 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -10,7 +10,6 @@ mod suggest; pub use self::suggest::SelfSource; pub use self::MethodError::*; -use crate::errors::OpMethodGenericParams; use crate::FnCtxt; use rustc_errors::{Applicability, Diagnostic, SubdiagnosticMessage}; use rustc_hir as hir; @@ -385,26 +384,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type parameters or early-bound regions. let tcx = self.tcx; let Some(method_item) = self.associated_value(trait_def_id, m_name) else { - tcx.dcx().span_delayed_bug( - obligation.cause.span, - "operator trait does not have corresponding operator method", - ); - return None; + bug!("expected associated item for operator trait") }; - if method_item.kind != ty::AssocKind::Fn { - self.dcx().span_delayed_bug(tcx.def_span(method_item.def_id), "not a method"); - return None; - } - let def_id = method_item.def_id; - let generics = tcx.generics_of(def_id); - - if generics.params.len() != 0 { - tcx.dcx().emit_fatal(OpMethodGenericParams { - span: tcx.def_span(method_item.def_id), - method_name: m_name.to_string(), - }); + if method_item.kind != ty::AssocKind::Fn { + span_bug!(tcx.def_span(def_id), "expected `{m_name}` to be an associated function"); } debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index bbe6d9e967044..9ce6189856194 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -1,7 +1,7 @@ //! Code related to processing overloaded binary and unary operators. use super::method::MethodCallee; -use super::{has_expected_num_generic_args, FnCtxt}; +use super::FnCtxt; use crate::Expectation; use rustc_ast as ast; use rustc_data_structures::packed::Pu128; @@ -887,25 +887,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty, op, opname, trait_did ); - // Catches cases like #83893, where a lang item is declared with the - // wrong number of generic arguments. Should have yielded an error - // elsewhere by now, but we have to catch it here so that we do not - // index `other_tys` out of bounds (if the lang item has too many - // generic arguments, `other_tys` is too short). - if !has_expected_num_generic_args( - self.tcx, - trait_did, - match op { - // Binary ops have a generic right-hand side, unary ops don't - Op::Binary(..) => 1, - Op::Unary(..) => 0, - }, - ) { - self.dcx() - .span_delayed_bug(span, "operator didn't have the right number of generic args"); - return Err(vec![]); - } - let opname = Ident::with_dummy_span(opname); let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip(); let input_types = opt_rhs_ty.as_slice(); diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index d626176377283..1eaaf30043b44 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -1,5 +1,5 @@ use crate::method::MethodCallee; -use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp}; +use crate::{FnCtxt, PlaceOp}; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir as hir; @@ -209,20 +209,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - // If the lang item was declared incorrectly, stop here so that we don't - // run into an ICE (#83893). The error is reported where the lang item is - // declared. - if !has_expected_num_generic_args( - self.tcx, - imm_tr, - match op { - PlaceOp::Deref => 0, - PlaceOp::Index => 1, - }, - ) { - return None; - } - self.lookup_method_in_trait( self.misc(span), Ident::with_dummy_span(imm_op), @@ -249,20 +235,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - // If the lang item was declared incorrectly, stop here so that we don't - // run into an ICE (#83893). The error is reported where the lang item is - // declared. - if !has_expected_num_generic_args( - self.tcx, - mut_tr, - match op { - PlaceOp::Deref => 0, - PlaceOp::Index => 1, - }, - ) { - return None; - } - self.lookup_method_in_trait( self.misc(span), Ident::with_dummy_span(mut_op), diff --git a/tests/ui/lang-items/bad-add-impl.rs b/tests/ui/lang-items/bad-add-impl.rs deleted file mode 100644 index 0c44edbe51a0c..0000000000000 --- a/tests/ui/lang-items/bad-add-impl.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![feature(no_core)] -#![feature(lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - -#[lang = "add"] -trait Add { - const add: u32 = 1u32; -} - -impl Add for u32 {} - -fn main() { - 1u32 + 1u32; - //~^ ERROR cannot add `u32` to `u32` -} diff --git a/tests/ui/lang-items/bad-add-impl.stderr b/tests/ui/lang-items/bad-add-impl.stderr deleted file mode 100644 index c5ad9ff2a0856..0000000000000 --- a/tests/ui/lang-items/bad-add-impl.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0369]: cannot add `u32` to `u32` - --> $DIR/bad-add-impl.rs:16:10 - | -LL | 1u32 + 1u32; - | ---- ^ ---- u32 - | | - | u32 - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr deleted file mode 100644 index ff603111e94c5..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:39:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:43:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr deleted file mode 100644 index ff603111e94c5..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:39:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:43:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs deleted file mode 100644 index 757c6538d05b0..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs +++ /dev/null @@ -1,49 +0,0 @@ -// revisions: fn_once_bad_item fn_once_bad_sig fn_mut_bad_item fn_mut_bad_sig fn_bad_item fn_bad_sig - -#![feature(lang_items)] -#![feature(no_core)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - -#[cfg(any(fn_bad_item, fn_bad_sig))] -#[lang = "fn"] -trait MyFn { - #[cfg(fn_bad_sig)] - fn call(i: i32) -> i32 { 0 } - - #[cfg(fn_bad_item)] - const call: i32 = 42; -} - -#[cfg(any(fn_mut_bad_item, fn_mut_bad_sig))] -#[lang = "fn_mut"] -trait MyFnMut { - #[cfg(fn_mut_bad_sig)] - fn call_mut(i: i32) -> i32 { 0 } - - #[cfg(fn_mut_bad_item)] - const call_mut: i32 = 42; -} - -#[cfg(any(fn_once_bad_item, fn_once_bad_sig))] -#[lang = "fn_once"] -trait MyFnOnce { - #[cfg(fn_once_bad_sig)] - fn call_once(i: i32) -> i32 { 0 } - - #[cfg(fn_once_bad_item)] - const call_once: i32 = 42; -} - -fn main() { - let a = || 42; - a(); - //~^ ERROR failed to find an overloaded call trait for closure call - - let mut i = 0; - let mut b = || { }; - b(); - //~^ ERROR failed to find an overloaded call trait for closure call -} diff --git a/tests/ui/lang-items/issue-31076.rs b/tests/ui/lang-items/issue-31076.rs deleted file mode 100644 index cdb196d4ff23f..0000000000000 --- a/tests/ui/lang-items/issue-31076.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(no_core, lang_items)] -#![no_core] - -#[lang="sized"] -trait Sized {} - -#[lang="add"] -trait Add {} - -impl Add for i32 {} - -fn main() { - let x = 5 + 6; - //~^ ERROR cannot add `i32` to `{integer}` - let y = 5i32 + 6i32; - //~^ ERROR cannot add `i32` to `i32` -} diff --git a/tests/ui/lang-items/issue-31076.stderr b/tests/ui/lang-items/issue-31076.stderr deleted file mode 100644 index ac0d9dc752879..0000000000000 --- a/tests/ui/lang-items/issue-31076.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0369]: cannot add `i32` to `{integer}` - --> $DIR/issue-31076.rs:13:15 - | -LL | let x = 5 + 6; - | - ^ - i32 - | | - | {integer} - -error[E0369]: cannot add `i32` to `i32` - --> $DIR/issue-31076.rs:15:18 - | -LL | let y = 5i32 + 6i32; - | ---- ^ ---- i32 - | | - | i32 - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/lang-items/issue-86238.rs b/tests/ui/lang-items/issue-86238.rs deleted file mode 100644 index 509f94f3834a5..0000000000000 --- a/tests/ui/lang-items/issue-86238.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Regression test for the ICE described in issue #86238. - -#![feature(lang_items)] -#![feature(no_core)] - -#![no_core] -fn main() { - let one = || {}; - one() - //~^ ERROR: failed to find an overloaded call trait for closure call - //~| HELP: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined -} -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} diff --git a/tests/ui/lang-items/issue-86238.stderr b/tests/ui/lang-items/issue-86238.stderr deleted file mode 100644 index b492904bcc73a..0000000000000 --- a/tests/ui/lang-items/issue-86238.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/issue-86238.rs:9:5 - | -LL | one() - | ^^^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 1 previous error - diff --git a/tests/ui/panic-handler/panic-handler-requires-panic-info.rs b/tests/ui/panic-handler/panic-handler-requires-panic-info.rs index f13c12fc52e4e..b59023b50e1e0 100644 --- a/tests/ui/panic-handler/panic-handler-requires-panic-info.rs +++ b/tests/ui/panic-handler/panic-handler-requires-panic-info.rs @@ -1,5 +1,4 @@ // compile-flags:-C panic=abort -// error-pattern: language item required, but not found: `panic_info` #![feature(lang_items)] #![feature(no_core)] @@ -8,6 +7,7 @@ #[panic_handler] fn panic() -> ! { + //~^ ERROR requires `panic_info` lang_item loop {} } diff --git a/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr b/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr index 06ff8e3098aa4..873f61a51632b 100644 --- a/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr +++ b/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr @@ -1,4 +1,8 @@ -error: language item required, but not found: `panic_info` +error: requires `panic_info` lang_item + --> $DIR/panic-handler-requires-panic-info.rs:9:1 + | +LL | fn panic() -> ! { + | ^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/invalid_operator_trait.rs b/tests/ui/traits/invalid_operator_trait.rs deleted file mode 100644 index 7ea3b0d5bac76..0000000000000 --- a/tests/ui/traits/invalid_operator_trait.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![crate_type = "lib"] -#![feature(lang_items)] -#![feature(no_core)] -#![no_core] - -#[lang="sized"] -pub trait Sized { - // Empty. -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, _: RHS) -> Self::Output; - //~^ ERROR `add` must not have any generic parameters -} - -#[allow(unreachable_code)] -fn ice(a: usize) { - let r = loop {}; - r = r + a; -} diff --git a/tests/ui/traits/invalid_operator_trait.stderr b/tests/ui/traits/invalid_operator_trait.stderr deleted file mode 100644 index f2e5e9080b16e..0000000000000 --- a/tests/ui/traits/invalid_operator_trait.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `add` must not have any generic parameters - --> $DIR/invalid_operator_trait.rs:15:5 - | -LL | fn add(self, _: RHS) -> Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - From bf4de3a874753bbee3323081c8b0c133444fed2d Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 24 Jan 2024 03:19:51 +0100 Subject: [PATCH 367/676] Remove `raw_os_nonzero` feature. --- library/core/src/ffi/mod.rs | 64 ++++--------------- library/std/src/lib.rs | 1 - .../src/sys/pal/unix/process/process_unix.rs | 7 +- .../pal/unix/process/process_unsupported.rs | 5 +- .../process_unsupported/wait_status.rs | 5 +- .../sys/pal/unix/process/process_vxworks.rs | 7 +- library/std/src/sys/pal/windows/c.rs | 4 +- 7 files changed, 26 insertions(+), 67 deletions(-) diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 7340ad90da509..44200926a32eb 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -11,7 +11,6 @@ use crate::fmt; use crate::marker::PhantomData; -use crate::num::*; use crate::ops::{Deref, DerefMut}; #[stable(feature = "core_c_str", since = "1.64.0")] @@ -19,7 +18,7 @@ pub use self::c_str::{CStr, FromBytesUntilNulError, FromBytesWithNulError}; mod c_str; -macro_rules! type_alias_no_nz { +macro_rules! type_alias { { $Docfile:tt, $Alias:ident = $Real:ty; $( $Cfg:tt )* @@ -31,49 +30,24 @@ macro_rules! type_alias_no_nz { } } -// To verify that the NonZero types in this file's macro invocations correspond -// -// perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2' -// -// NB this does not check that the main c_* types are right. - -macro_rules! type_alias { - { - $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty; - $( $Cfg:tt )* - } => { - type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* } - - #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")] - #[unstable(feature = "raw_os_nonzero", issue = "82363")] - $( $Cfg )* - pub type $NZAlias = $NZReal; - } -} - -type_alias! { "c_char.md", c_char = c_char_definition::c_char, NonZero_c_char = c_char_definition::NonZero_c_char; -#[doc(cfg(all()))] } +type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] } -type_alias! { "c_schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; } -type_alias! { "c_uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; } -type_alias! { "c_short.md", c_short = i16, NonZero_c_short = NonZeroI16; } -type_alias! { "c_ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; } +type_alias! { "c_schar.md", c_schar = i8; } +type_alias! { "c_uchar.md", c_uchar = u8; } +type_alias! { "c_short.md", c_short = i16; } +type_alias! { "c_ushort.md", c_ushort = u16; } -type_alias! { "c_int.md", c_int = c_int_definition::c_int, NonZero_c_int = c_int_definition::NonZero_c_int; -#[doc(cfg(all()))] } -type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint, NonZero_c_uint = c_int_definition::NonZero_c_uint; -#[doc(cfg(all()))] } +type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] } +type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] } -type_alias! { "c_long.md", c_long = c_long_definition::c_long, NonZero_c_long = c_long_definition::NonZero_c_long; -#[doc(cfg(all()))] } -type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong, NonZero_c_ulong = c_long_definition::NonZero_c_ulong; -#[doc(cfg(all()))] } +type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] } +type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] } -type_alias! { "c_longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; } -type_alias! { "c_ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; } +type_alias! { "c_longlong.md", c_longlong = i64; } +type_alias! { "c_ulonglong.md", c_ulonglong = u64; } -type_alias_no_nz! { "c_float.md", c_float = f32; } -type_alias_no_nz! { "c_double.md", c_double = f64; } +type_alias! { "c_float.md", c_float = f32; } +type_alias! { "c_double.md", c_double = f64; } /// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++). /// @@ -152,11 +126,9 @@ mod c_char_definition { target_os = "horizon" ))] { pub type c_char = u8; - pub type NonZero_c_char = crate::num::NonZeroU8; } else { // On every other target, c_char is signed. pub type c_char = i8; - pub type NonZero_c_char = crate::num::NonZeroI8; } } } @@ -165,14 +137,10 @@ mod c_int_definition { cfg_if! { if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { pub type c_int = i16; - pub type NonZero_c_int = crate::num::NonZeroI16; pub type c_uint = u16; - pub type NonZero_c_uint = crate::num::NonZeroU16; } else { pub type c_int = i32; - pub type NonZero_c_int = crate::num::NonZeroI32; pub type c_uint = u32; - pub type NonZero_c_uint = crate::num::NonZeroU32; } } } @@ -181,15 +149,11 @@ mod c_long_definition { cfg_if! { if #[cfg(all(target_pointer_width = "64", not(windows)))] { pub type c_long = i64; - pub type NonZero_c_long = crate::num::NonZeroI64; pub type c_ulong = u64; - pub type NonZero_c_ulong = crate::num::NonZeroU64; } else { // The minimal size of `long` in the C standard is 32 bits pub type c_long = i32; - pub type NonZero_c_long = crate::num::NonZeroI32; pub type c_ulong = u32; - pub type NonZero_c_ulong = crate::num::NonZeroU32; } } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2e458562744bf..ccc7a1592312d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -338,7 +338,6 @@ #![feature(portable_simd)] #![feature(prelude_2024)] #![feature(ptr_as_uninit)] -#![feature(raw_os_nonzero)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_range)] diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index df0fe2bb9d84a..94c4c56bd51cf 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -1,11 +1,10 @@ use crate::fmt; use crate::io::{self, Error, ErrorKind}; use crate::mem; -use crate::num::NonZeroI32; +use crate::num::{NonZero, NonZeroI32}; use crate::sys; use crate::sys::cvt; use crate::sys::process::process_common::*; -use core::ffi::NonZero_c_int; #[cfg(target_os = "linux")] use crate::os::linux::process::PidFd; @@ -935,7 +934,7 @@ impl ExitStatus { // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. - match NonZero_c_int::try_from(self.0) { + match NonZero::try_from(self.0) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), } @@ -1092,7 +1091,7 @@ impl fmt::Display for ExitStatus { } #[derive(PartialEq, Eq, Clone, Copy)] -pub struct ExitStatusError(NonZero_c_int); +pub struct ExitStatusError(NonZero); impl Into for ExitStatusError { fn into(self) -> ExitStatus { diff --git a/library/std/src/sys/pal/unix/process/process_unsupported.rs b/library/std/src/sys/pal/unix/process/process_unsupported.rs index 9453c8a384e24..89a2a0c6e567b 100644 --- a/library/std/src/sys/pal/unix/process/process_unsupported.rs +++ b/library/std/src/sys/pal/unix/process/process_unsupported.rs @@ -1,9 +1,8 @@ use crate::fmt; use crate::io; -use crate::num::NonZeroI32; +use crate::num::{NonZero, NonZeroI32}; use crate::sys::pal::unix::unsupported::*; use crate::sys::process::process_common::*; -use core::ffi::NonZero_c_int; use libc::{c_int, pid_t}; @@ -59,7 +58,7 @@ mod wait_status; pub use wait_status::ExitStatus; #[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub struct ExitStatusError(NonZero_c_int); +pub struct ExitStatusError(NonZero); impl Into for ExitStatusError { fn into(self) -> ExitStatus { diff --git a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs b/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs index 72b7ae18cff27..e6dfadcf4a4cf 100644 --- a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs +++ b/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs @@ -1,10 +1,9 @@ //! Emulated wait status for non-Unix #[cfg(unix) platforms //! //! Separate module to facilitate testing against a real Unix implementation. -use core::ffi::NonZero_c_int; - use crate::ffi::c_int; use crate::fmt; +use crate::num::NonZero; use super::ExitStatusError; @@ -50,7 +49,7 @@ impl ExitStatus { // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. - match NonZero_c_int::try_from(self.wait_status) { + match NonZero::try_from(self.wait_status) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), } diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/pal/unix/process/process_vxworks.rs index 1ff2b2fb3833f..5b4e94d0f1b97 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/pal/unix/process/process_vxworks.rs @@ -1,11 +1,10 @@ use crate::fmt; use crate::io::{self, Error, ErrorKind}; -use crate::num::NonZeroI32; +use crate::num::{NonZero, NonZeroI32}; use crate::sys; use crate::sys::cvt; use crate::sys::process::process_common::*; use crate::sys_common::thread; -use core::ffi::NonZero_c_int; use libc::RTP_ID; use libc::{self, c_char, c_int}; @@ -197,7 +196,7 @@ impl ExitStatus { // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. - match NonZero_c_int::try_from(self.0) { + match NonZero::try_from(self.0) { Ok(failure) => Err(ExitStatusError(failure)), Err(_) => Ok(()), } @@ -249,7 +248,7 @@ impl fmt::Display for ExitStatus { } #[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub struct ExitStatusError(NonZero_c_int); +pub struct ExitStatusError(NonZero); impl Into for ExitStatusError { fn into(self) -> ExitStatus { diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index d55d9bace811c..1a59ac9a9cadf 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -7,17 +7,17 @@ use crate::ffi::CStr; use crate::mem; +use crate::num::NonZero; pub use crate::os::raw::c_int; use crate::os::raw::{c_char, c_long, c_longlong, c_uint, c_ulong, c_ushort, c_void}; use crate::os::windows::io::{AsRawHandle, BorrowedHandle}; use crate::ptr; -use core::ffi::NonZero_c_ulong; mod windows_sys; pub use windows_sys::*; pub type DWORD = c_ulong; -pub type NonZeroDWORD = NonZero_c_ulong; +pub type NonZeroDWORD = NonZero; pub type LARGE_INTEGER = c_longlong; #[cfg_attr(target_vendor = "uwp", allow(unused))] pub type LONG = c_long; From ed5562987969ab063367418d6847ac4a224b51e7 Mon Sep 17 00:00:00 2001 From: Marek 'seqre' Grzelak Date: Sat, 27 Jan 2024 22:59:40 -0600 Subject: [PATCH 368/676] Move multiple UI issue tests to subdirectories Issue tests numbered 1920, 3668, 5997, 23302, 32122, 40510, 57741, 71676, and 76077 were moved to relevant better-named subdirectories. ISSUES_ENTRY_LIMIT was adjusted to match new number of files and FIXME note was expanded. --- src/tools/tidy/src/ui_tests.rs | 7 +++++-- .../auxiliary/issue-1920.rs | 0 .../issues/{ => issue-1920-absolute-paths}/issue-1920-1.rs | 0 .../{ => issue-1920-absolute-paths}/issue-1920-1.stderr | 0 .../issues/{ => issue-1920-absolute-paths}/issue-1920-2.rs | 0 .../{ => issue-1920-absolute-paths}/issue-1920-2.stderr | 0 .../issues/{ => issue-1920-absolute-paths}/issue-1920-3.rs | 0 .../{ => issue-1920-absolute-paths}/issue-1920-3.stderr | 0 .../issue-23302-1.rs | 0 .../issue-23302-1.stderr | 0 .../issue-23302-2.rs | 0 .../issue-23302-2.stderr | 0 .../issue-23302-3.rs | 0 .../issue-23302-3.stderr | 0 .../issue-32122-1.fixed | 0 .../issue-32122-1.rs | 0 .../issue-32122-1.stderr | 0 .../issue-32122-2.fixed | 0 .../issue-32122-2.rs | 0 .../issue-32122-2.stderr | 0 .../issue-3668-2.fixed | 0 .../issue-3668-2.rs | 0 .../issue-3668-2.stderr | 0 .../issue-3668.rs | 0 .../issue-3668.stderr | 0 .../issue-40510-1.migrate.stderr | 0 .../issue-40510-1.rs | 0 .../issue-40510-1.stderr | 0 .../issue-40510-2.rs | 0 .../issue-40510-3.migrate.stderr | 0 .../issue-40510-3.rs | 0 .../issue-40510-3.stderr | 0 .../issue-40510-4.rs | 0 .../issue-57741-1.rs | 0 .../issue-57741-1.stderr | 0 .../issue-57741.fixed | 0 .../issue-57741.rs | 0 .../issue-57741.stderr | 0 .../issue-5997-enum.rs | 0 .../issue-5997-enum.stderr | 0 .../issue-5997-struct.rs | 0 .../issue-5997-struct.stderr | 0 .../{ => issue-5997-outer-generic-parameter}/issue-5997.rs | 0 .../{ => issue-71676-suggest-deref}/issue-71676-1.fixed | 0 .../{ => issue-71676-suggest-deref}/issue-71676-1.rs | 0 .../{ => issue-71676-suggest-deref}/issue-71676-1.stderr | 0 .../{ => issue-71676-suggest-deref}/issue-71676-2.rs | 0 .../{ => issue-71676-suggest-deref}/issue-71676-2.stderr | 0 .../issue-76077-1.fixed | 0 .../issue-76077-1.rs | 0 .../issue-76077-1.stderr | 0 .../issue-76077.rs | 0 .../issue-76077.stderr | 0 53 files changed, 5 insertions(+), 2 deletions(-) rename tests/ui/issues/{ => issue-1920-absolute-paths}/auxiliary/issue-1920.rs (100%) rename tests/ui/issues/{ => issue-1920-absolute-paths}/issue-1920-1.rs (100%) rename tests/ui/issues/{ => issue-1920-absolute-paths}/issue-1920-1.stderr (100%) rename tests/ui/issues/{ => issue-1920-absolute-paths}/issue-1920-2.rs (100%) rename tests/ui/issues/{ => issue-1920-absolute-paths}/issue-1920-2.stderr (100%) rename tests/ui/issues/{ => issue-1920-absolute-paths}/issue-1920-3.rs (100%) rename tests/ui/issues/{ => issue-1920-absolute-paths}/issue-1920-3.stderr (100%) rename tests/ui/issues/{ => issue-23302-enum-infinite-recursion}/issue-23302-1.rs (100%) rename tests/ui/issues/{ => issue-23302-enum-infinite-recursion}/issue-23302-1.stderr (100%) rename tests/ui/issues/{ => issue-23302-enum-infinite-recursion}/issue-23302-2.rs (100%) rename tests/ui/issues/{ => issue-23302-enum-infinite-recursion}/issue-23302-2.stderr (100%) rename tests/ui/issues/{ => issue-23302-enum-infinite-recursion}/issue-23302-3.rs (100%) rename tests/ui/issues/{ => issue-23302-enum-infinite-recursion}/issue-23302-3.stderr (100%) rename tests/ui/issues/{ => issue-32122-deref-coercions-composition}/issue-32122-1.fixed (100%) rename tests/ui/issues/{ => issue-32122-deref-coercions-composition}/issue-32122-1.rs (100%) rename tests/ui/issues/{ => issue-32122-deref-coercions-composition}/issue-32122-1.stderr (100%) rename tests/ui/issues/{ => issue-32122-deref-coercions-composition}/issue-32122-2.fixed (100%) rename tests/ui/issues/{ => issue-32122-deref-coercions-composition}/issue-32122-2.rs (100%) rename tests/ui/issues/{ => issue-32122-deref-coercions-composition}/issue-32122-2.stderr (100%) rename tests/ui/issues/{ => issue-3668-non-constant-value-in-constant}/issue-3668-2.fixed (100%) rename tests/ui/issues/{ => issue-3668-non-constant-value-in-constant}/issue-3668-2.rs (100%) rename tests/ui/issues/{ => issue-3668-non-constant-value-in-constant}/issue-3668-2.stderr (100%) rename tests/ui/issues/{ => issue-3668-non-constant-value-in-constant}/issue-3668.rs (100%) rename tests/ui/issues/{ => issue-3668-non-constant-value-in-constant}/issue-3668.stderr (100%) rename tests/ui/issues/{ => issue-40510-captured-variable-return}/issue-40510-1.migrate.stderr (100%) rename tests/ui/issues/{ => issue-40510-captured-variable-return}/issue-40510-1.rs (100%) rename tests/ui/issues/{ => issue-40510-captured-variable-return}/issue-40510-1.stderr (100%) rename tests/ui/issues/{ => issue-40510-captured-variable-return}/issue-40510-2.rs (100%) rename tests/ui/issues/{ => issue-40510-captured-variable-return}/issue-40510-3.migrate.stderr (100%) rename tests/ui/issues/{ => issue-40510-captured-variable-return}/issue-40510-3.rs (100%) rename tests/ui/issues/{ => issue-40510-captured-variable-return}/issue-40510-3.stderr (100%) rename tests/ui/issues/{ => issue-40510-captured-variable-return}/issue-40510-4.rs (100%) rename tests/ui/issues/{ => issue-57741-dereference-boxed-value}/issue-57741-1.rs (100%) rename tests/ui/issues/{ => issue-57741-dereference-boxed-value}/issue-57741-1.stderr (100%) rename tests/ui/issues/{ => issue-57741-dereference-boxed-value}/issue-57741.fixed (100%) rename tests/ui/issues/{ => issue-57741-dereference-boxed-value}/issue-57741.rs (100%) rename tests/ui/issues/{ => issue-57741-dereference-boxed-value}/issue-57741.stderr (100%) rename tests/ui/issues/{ => issue-5997-outer-generic-parameter}/issue-5997-enum.rs (100%) rename tests/ui/issues/{ => issue-5997-outer-generic-parameter}/issue-5997-enum.stderr (100%) rename tests/ui/issues/{ => issue-5997-outer-generic-parameter}/issue-5997-struct.rs (100%) rename tests/ui/issues/{ => issue-5997-outer-generic-parameter}/issue-5997-struct.stderr (100%) rename tests/ui/issues/{ => issue-5997-outer-generic-parameter}/issue-5997.rs (100%) rename tests/ui/issues/{ => issue-71676-suggest-deref}/issue-71676-1.fixed (100%) rename tests/ui/issues/{ => issue-71676-suggest-deref}/issue-71676-1.rs (100%) rename tests/ui/issues/{ => issue-71676-suggest-deref}/issue-71676-1.stderr (100%) rename tests/ui/issues/{ => issue-71676-suggest-deref}/issue-71676-2.rs (100%) rename tests/ui/issues/{ => issue-71676-suggest-deref}/issue-71676-2.stderr (100%) rename tests/ui/issues/{ => issue-76077-inaccesible-private-fields}/issue-76077-1.fixed (100%) rename tests/ui/issues/{ => issue-76077-inaccesible-private-fields}/issue-76077-1.rs (100%) rename tests/ui/issues/{ => issue-76077-inaccesible-private-fields}/issue-76077-1.stderr (100%) rename tests/ui/issues/{ => issue-76077-inaccesible-private-fields}/issue-76077.rs (100%) rename tests/ui/issues/{ => issue-76077-inaccesible-private-fields}/issue-76077.stderr (100%) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 85553d2e3384a..451276b5ac157 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -8,9 +8,12 @@ use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; +// FIXME: GitHub's UI truncates file lists that exceed 1000 entries, so these +// should all be 1000 or lower. Limits significantly smaller than 1000 are also +// desirable, because large numbers of files are unwieldy in general. See issue +// #73494. const ENTRY_LIMIT: usize = 900; -// FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1849; +const ISSUES_ENTRY_LIMIT: usize = 1807; const ROOT_ENTRY_LIMIT: usize = 870; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/tests/ui/issues/auxiliary/issue-1920.rs b/tests/ui/issues/issue-1920-absolute-paths/auxiliary/issue-1920.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-1920.rs rename to tests/ui/issues/issue-1920-absolute-paths/auxiliary/issue-1920.rs diff --git a/tests/ui/issues/issue-1920-1.rs b/tests/ui/issues/issue-1920-absolute-paths/issue-1920-1.rs similarity index 100% rename from tests/ui/issues/issue-1920-1.rs rename to tests/ui/issues/issue-1920-absolute-paths/issue-1920-1.rs diff --git a/tests/ui/issues/issue-1920-1.stderr b/tests/ui/issues/issue-1920-absolute-paths/issue-1920-1.stderr similarity index 100% rename from tests/ui/issues/issue-1920-1.stderr rename to tests/ui/issues/issue-1920-absolute-paths/issue-1920-1.stderr diff --git a/tests/ui/issues/issue-1920-2.rs b/tests/ui/issues/issue-1920-absolute-paths/issue-1920-2.rs similarity index 100% rename from tests/ui/issues/issue-1920-2.rs rename to tests/ui/issues/issue-1920-absolute-paths/issue-1920-2.rs diff --git a/tests/ui/issues/issue-1920-2.stderr b/tests/ui/issues/issue-1920-absolute-paths/issue-1920-2.stderr similarity index 100% rename from tests/ui/issues/issue-1920-2.stderr rename to tests/ui/issues/issue-1920-absolute-paths/issue-1920-2.stderr diff --git a/tests/ui/issues/issue-1920-3.rs b/tests/ui/issues/issue-1920-absolute-paths/issue-1920-3.rs similarity index 100% rename from tests/ui/issues/issue-1920-3.rs rename to tests/ui/issues/issue-1920-absolute-paths/issue-1920-3.rs diff --git a/tests/ui/issues/issue-1920-3.stderr b/tests/ui/issues/issue-1920-absolute-paths/issue-1920-3.stderr similarity index 100% rename from tests/ui/issues/issue-1920-3.stderr rename to tests/ui/issues/issue-1920-absolute-paths/issue-1920-3.stderr diff --git a/tests/ui/issues/issue-23302-1.rs b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.rs similarity index 100% rename from tests/ui/issues/issue-23302-1.rs rename to tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.rs diff --git a/tests/ui/issues/issue-23302-1.stderr b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr similarity index 100% rename from tests/ui/issues/issue-23302-1.stderr rename to tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr diff --git a/tests/ui/issues/issue-23302-2.rs b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.rs similarity index 100% rename from tests/ui/issues/issue-23302-2.rs rename to tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.rs diff --git a/tests/ui/issues/issue-23302-2.stderr b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr similarity index 100% rename from tests/ui/issues/issue-23302-2.stderr rename to tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr diff --git a/tests/ui/issues/issue-23302-3.rs b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-3.rs similarity index 100% rename from tests/ui/issues/issue-23302-3.rs rename to tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-3.rs diff --git a/tests/ui/issues/issue-23302-3.stderr b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-3.stderr similarity index 100% rename from tests/ui/issues/issue-23302-3.stderr rename to tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-3.stderr diff --git a/tests/ui/issues/issue-32122-1.fixed b/tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-1.fixed similarity index 100% rename from tests/ui/issues/issue-32122-1.fixed rename to tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-1.fixed diff --git a/tests/ui/issues/issue-32122-1.rs b/tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-1.rs similarity index 100% rename from tests/ui/issues/issue-32122-1.rs rename to tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-1.rs diff --git a/tests/ui/issues/issue-32122-1.stderr b/tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-1.stderr similarity index 100% rename from tests/ui/issues/issue-32122-1.stderr rename to tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-1.stderr diff --git a/tests/ui/issues/issue-32122-2.fixed b/tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-2.fixed similarity index 100% rename from tests/ui/issues/issue-32122-2.fixed rename to tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-2.fixed diff --git a/tests/ui/issues/issue-32122-2.rs b/tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-2.rs similarity index 100% rename from tests/ui/issues/issue-32122-2.rs rename to tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-2.rs diff --git a/tests/ui/issues/issue-32122-2.stderr b/tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-2.stderr similarity index 100% rename from tests/ui/issues/issue-32122-2.stderr rename to tests/ui/issues/issue-32122-deref-coercions-composition/issue-32122-2.stderr diff --git a/tests/ui/issues/issue-3668-2.fixed b/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.fixed similarity index 100% rename from tests/ui/issues/issue-3668-2.fixed rename to tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.fixed diff --git a/tests/ui/issues/issue-3668-2.rs b/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.rs similarity index 100% rename from tests/ui/issues/issue-3668-2.rs rename to tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.rs diff --git a/tests/ui/issues/issue-3668-2.stderr b/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.stderr similarity index 100% rename from tests/ui/issues/issue-3668-2.stderr rename to tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.stderr diff --git a/tests/ui/issues/issue-3668.rs b/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.rs similarity index 100% rename from tests/ui/issues/issue-3668.rs rename to tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.rs diff --git a/tests/ui/issues/issue-3668.stderr b/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.stderr similarity index 100% rename from tests/ui/issues/issue-3668.stderr rename to tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.stderr diff --git a/tests/ui/issues/issue-40510-1.migrate.stderr b/tests/ui/issues/issue-40510-captured-variable-return/issue-40510-1.migrate.stderr similarity index 100% rename from tests/ui/issues/issue-40510-1.migrate.stderr rename to tests/ui/issues/issue-40510-captured-variable-return/issue-40510-1.migrate.stderr diff --git a/tests/ui/issues/issue-40510-1.rs b/tests/ui/issues/issue-40510-captured-variable-return/issue-40510-1.rs similarity index 100% rename from tests/ui/issues/issue-40510-1.rs rename to tests/ui/issues/issue-40510-captured-variable-return/issue-40510-1.rs diff --git a/tests/ui/issues/issue-40510-1.stderr b/tests/ui/issues/issue-40510-captured-variable-return/issue-40510-1.stderr similarity index 100% rename from tests/ui/issues/issue-40510-1.stderr rename to tests/ui/issues/issue-40510-captured-variable-return/issue-40510-1.stderr diff --git a/tests/ui/issues/issue-40510-2.rs b/tests/ui/issues/issue-40510-captured-variable-return/issue-40510-2.rs similarity index 100% rename from tests/ui/issues/issue-40510-2.rs rename to tests/ui/issues/issue-40510-captured-variable-return/issue-40510-2.rs diff --git a/tests/ui/issues/issue-40510-3.migrate.stderr b/tests/ui/issues/issue-40510-captured-variable-return/issue-40510-3.migrate.stderr similarity index 100% rename from tests/ui/issues/issue-40510-3.migrate.stderr rename to tests/ui/issues/issue-40510-captured-variable-return/issue-40510-3.migrate.stderr diff --git a/tests/ui/issues/issue-40510-3.rs b/tests/ui/issues/issue-40510-captured-variable-return/issue-40510-3.rs similarity index 100% rename from tests/ui/issues/issue-40510-3.rs rename to tests/ui/issues/issue-40510-captured-variable-return/issue-40510-3.rs diff --git a/tests/ui/issues/issue-40510-3.stderr b/tests/ui/issues/issue-40510-captured-variable-return/issue-40510-3.stderr similarity index 100% rename from tests/ui/issues/issue-40510-3.stderr rename to tests/ui/issues/issue-40510-captured-variable-return/issue-40510-3.stderr diff --git a/tests/ui/issues/issue-40510-4.rs b/tests/ui/issues/issue-40510-captured-variable-return/issue-40510-4.rs similarity index 100% rename from tests/ui/issues/issue-40510-4.rs rename to tests/ui/issues/issue-40510-captured-variable-return/issue-40510-4.rs diff --git a/tests/ui/issues/issue-57741-1.rs b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741-1.rs similarity index 100% rename from tests/ui/issues/issue-57741-1.rs rename to tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741-1.rs diff --git a/tests/ui/issues/issue-57741-1.stderr b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741-1.stderr similarity index 100% rename from tests/ui/issues/issue-57741-1.stderr rename to tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741-1.stderr diff --git a/tests/ui/issues/issue-57741.fixed b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.fixed similarity index 100% rename from tests/ui/issues/issue-57741.fixed rename to tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.fixed diff --git a/tests/ui/issues/issue-57741.rs b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.rs similarity index 100% rename from tests/ui/issues/issue-57741.rs rename to tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.rs diff --git a/tests/ui/issues/issue-57741.stderr b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr similarity index 100% rename from tests/ui/issues/issue-57741.stderr rename to tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr diff --git a/tests/ui/issues/issue-5997-enum.rs b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs similarity index 100% rename from tests/ui/issues/issue-5997-enum.rs rename to tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs diff --git a/tests/ui/issues/issue-5997-enum.stderr b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr similarity index 100% rename from tests/ui/issues/issue-5997-enum.stderr rename to tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr diff --git a/tests/ui/issues/issue-5997-struct.rs b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs similarity index 100% rename from tests/ui/issues/issue-5997-struct.rs rename to tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs diff --git a/tests/ui/issues/issue-5997-struct.stderr b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr similarity index 100% rename from tests/ui/issues/issue-5997-struct.stderr rename to tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr diff --git a/tests/ui/issues/issue-5997.rs b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs similarity index 100% rename from tests/ui/issues/issue-5997.rs rename to tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs diff --git a/tests/ui/issues/issue-71676-1.fixed b/tests/ui/issues/issue-71676-suggest-deref/issue-71676-1.fixed similarity index 100% rename from tests/ui/issues/issue-71676-1.fixed rename to tests/ui/issues/issue-71676-suggest-deref/issue-71676-1.fixed diff --git a/tests/ui/issues/issue-71676-1.rs b/tests/ui/issues/issue-71676-suggest-deref/issue-71676-1.rs similarity index 100% rename from tests/ui/issues/issue-71676-1.rs rename to tests/ui/issues/issue-71676-suggest-deref/issue-71676-1.rs diff --git a/tests/ui/issues/issue-71676-1.stderr b/tests/ui/issues/issue-71676-suggest-deref/issue-71676-1.stderr similarity index 100% rename from tests/ui/issues/issue-71676-1.stderr rename to tests/ui/issues/issue-71676-suggest-deref/issue-71676-1.stderr diff --git a/tests/ui/issues/issue-71676-2.rs b/tests/ui/issues/issue-71676-suggest-deref/issue-71676-2.rs similarity index 100% rename from tests/ui/issues/issue-71676-2.rs rename to tests/ui/issues/issue-71676-suggest-deref/issue-71676-2.rs diff --git a/tests/ui/issues/issue-71676-2.stderr b/tests/ui/issues/issue-71676-suggest-deref/issue-71676-2.stderr similarity index 100% rename from tests/ui/issues/issue-71676-2.stderr rename to tests/ui/issues/issue-71676-suggest-deref/issue-71676-2.stderr diff --git a/tests/ui/issues/issue-76077-1.fixed b/tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077-1.fixed similarity index 100% rename from tests/ui/issues/issue-76077-1.fixed rename to tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077-1.fixed diff --git a/tests/ui/issues/issue-76077-1.rs b/tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077-1.rs similarity index 100% rename from tests/ui/issues/issue-76077-1.rs rename to tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077-1.rs diff --git a/tests/ui/issues/issue-76077-1.stderr b/tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077-1.stderr similarity index 100% rename from tests/ui/issues/issue-76077-1.stderr rename to tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077-1.stderr diff --git a/tests/ui/issues/issue-76077.rs b/tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077.rs similarity index 100% rename from tests/ui/issues/issue-76077.rs rename to tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077.rs diff --git a/tests/ui/issues/issue-76077.stderr b/tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077.stderr similarity index 100% rename from tests/ui/issues/issue-76077.stderr rename to tests/ui/issues/issue-76077-inaccesible-private-fields/issue-76077.stderr From fc964fb439473c84a47444f89e5cf4c570b98f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Jan 2024 23:33:02 +0000 Subject: [PATCH 369/676] review comments --- .../rustc_hir_analysis/src/astconv/errors.rs | 25 ++++++----------- .../rustc_hir_typeck/src/method/suggest.rs | 28 +++++++------------ 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index b2d5d3885d938..fa7d9799dbd2e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -6,6 +6,7 @@ use crate::errors::{ use crate::fluent_generated as fluent; use crate::traits::error_reporting::report_object_safety_error; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; +use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordMap; use rustc_errors::{pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; @@ -461,14 +462,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return err.emit(); } - let mut bound_spans: FxHashMap> = Default::default(); + let mut bound_spans: SortedMap> = Default::default(); let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); match &self_ty.kind() { // Point at the type that couldn't satisfy the bound. ty::Adt(def, _) => { - bound_spans.entry(tcx.def_span(def.did())).or_default().push(msg) + bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) } // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _, _) => { @@ -476,8 +477,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match pred.skip_binder() { ty::ExistentialPredicate::Trait(tr) => { bound_spans - .entry(tcx.def_span(tr.def_id)) - .or_default() + .get_mut_or_insert_default(tcx.def_span(tr.def_id)) .push(msg.clone()); } ty::ExistentialPredicate::Projection(_) @@ -488,8 +488,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Point at the closure that couldn't satisfy the bound. ty::Closure(def_id, _) => { bound_spans - .entry(tcx.def_span(*def_id)) - .or_default() + .get_mut_or_insert_default(tcx.def_span(*def_id)) .push(format!("`{quiet}`")); } _ => {} @@ -559,21 +558,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds") ); - let mut bound_spans: Vec<(Span, Vec)> = bound_spans - .into_iter() - .map(|(span, mut bounds)| { - bounds.sort(); - bounds.dedup(); - (span, bounds) - }) - .collect(); - bound_spans.sort_by_key(|(span, _)| *span); - for (span, bounds) in bound_spans { + for (span, mut bounds) in bound_spans { if !tcx.sess.source_map().is_span_accessible(span) { continue; } + bounds.sort(); + bounds.dedup(); let msg = match &bounds[..] { [bound] => format!("doesn't satisfy {bound}"), + bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()), [bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")), [] => unreachable!(), }; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 0499a46dbb826..677d224065195 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -9,7 +9,8 @@ use crate::Expectation; use crate::FnCtxt; use rustc_ast::ast::Mutability; use rustc_attr::parse_confusables; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::StashKey; use rustc_errors::{ @@ -538,7 +539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - let mut bound_spans: FxHashMap> = Default::default(); + let mut bound_spans: SortedMap> = Default::default(); let mut restrict_type_params = false; let mut unsatisfied_bounds = false; if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { @@ -637,7 +638,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &self_ty.kind() { // Point at the type that couldn't satisfy the bound. ty::Adt(def, _) => { - bound_spans.entry(tcx.def_span(def.did())).or_default().push(msg) + bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) } // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _, _) => { @@ -645,8 +646,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match pred.skip_binder() { ty::ExistentialPredicate::Trait(tr) => { bound_spans - .entry(tcx.def_span(tr.def_id)) - .or_default() + .get_mut_or_insert_default(tcx.def_span(tr.def_id)) .push(msg.clone()); } ty::ExistentialPredicate::Projection(_) @@ -657,8 +657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Point at the closure that couldn't satisfy the bound. ty::Closure(def_id, _) => { bound_spans - .entry(tcx.def_span(*def_id)) - .or_default() + .get_mut_or_insert_default(tcx.def_span(*def_id)) .push(format!("`{quiet}`")); } _ => {} @@ -1167,20 +1166,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name); - #[allow(rustc::potential_query_instability)] // We immediately sort the resulting Vec. - let mut bound_spans: Vec<(Span, Vec)> = bound_spans - .into_iter() - .map(|(span, mut bounds)| { - bounds.sort(); - bounds.dedup(); - (span, bounds) - }) - .collect(); - bound_spans.sort_by_key(|(span, _)| *span); - for (span, bounds) in bound_spans { + for (span, mut bounds) in bound_spans { if !tcx.sess.source_map().is_span_accessible(span) { continue; } + bounds.sort(); + bounds.dedup(); let pre = if Some(span) == ty_span { ty_span.take(); format!( @@ -1192,6 +1183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let msg = match &bounds[..] { [bound] => format!("{pre}doesn't satisfy {bound}"), + bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()), [bounds @ .., last] => { format!("{pre}doesn't satisfy {} or {last}", bounds.join(", ")) } From 03545161e68c1b8c3fe052243e372ee75e4ec513 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 9 Oct 2023 14:25:31 +0100 Subject: [PATCH 370/676] Handle out of memory errors in io:Read::read_to_end() --- library/std/src/io/buffered/bufreader.rs | 1 + library/std/src/io/impls.rs | 5 ++-- library/std/src/io/mod.rs | 38 +++++++++++++++++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 6c7494a6a6ff9..e920500d7d07f 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -345,6 +345,7 @@ impl Read for BufReader { // delegate to the inner implementation. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let inner_buf = self.buffer(); + buf.try_reserve(inner_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?; buf.extend_from_slice(inner_buf); let nread = inner_buf.len(); self.discard_buffer(); diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index d8c8d933eb403..557e64dc8674e 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -303,8 +303,9 @@ impl Read for &[u8] { #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - buf.extend_from_slice(*self); let len = self.len(); + buf.try_reserve(len).map_err(|_| ErrorKind::OutOfMemory)?; + buf.extend_from_slice(*self); *self = &self[len..]; Ok(len) } @@ -451,7 +452,7 @@ impl Read for VecDeque { fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { // The total len is known upfront so we can reserve it in a single call. let len = self.len(); - buf.reserve(len); + buf.try_reserve(len).map_err(|_| ErrorKind::OutOfMemory)?; let (front, back) = self.as_slices(); buf.extend_from_slice(front); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index e3aa973741f1f..8fca66fa17c5e 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -430,6 +430,8 @@ pub(crate) fn default_read_to_end( loop { match r.read(&mut probe) { Ok(n) => { + // there is no way to recover from allocation failure here + // because the data has already been read. buf.extend_from_slice(&probe[..n]); return Ok(n); } @@ -462,7 +464,8 @@ pub(crate) fn default_read_to_end( } if buf.len() == buf.capacity() { - buf.reserve(PROBE_SIZE); // buf is full, need more space + // buf is full, need more space + buf.try_reserve(PROBE_SIZE).map_err(|_| ErrorKind::OutOfMemory)?; } let mut spare = buf.spare_capacity_mut(); @@ -815,6 +818,39 @@ pub trait Read { /// file.) /// /// [`std::fs::read`]: crate::fs::read + /// + /// ## Implementing `read_to_end` + /// + /// When implementing the `io::Read` trait, it is recommended to allocate + /// memory using [`Vec::try_reserve`]. However, this behavior is not guaranteed + /// by all implementations, and `read_to_end` may not handle out-of-memory + /// situations gracefully. + /// + /// ```no_run + /// # use std::io::{self, BufRead}; + /// # struct Example { example_datasource: io::Empty } impl Example { + /// # fn get_some_data_for_the_example(&self) -> &'static [u8] { &[] } + /// fn read_to_end(&mut self, dest_vec: &mut Vec) -> io::Result { + /// let initial_vec_len = dest_vec.len(); + /// loop { + /// let src_buf = self.example_datasource.fill_buf()?; + /// if src_buf.is_empty() { + /// break; + /// } + /// dest_vec.try_reserve(src_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?; + /// dest_vec.extend_from_slice(src_buf); + /// + /// // Any irreversible side effects should happen after `try_reserve` succeeds, + /// // to avoid losing data on allocation error. + /// let read = src_buf.len(); + /// self.example_datasource.consume(read); + /// } + /// Ok(dest_vec.len() - initial_vec_len) + /// } + /// # } + /// ``` + /// + /// [`Vec::try_reserve`]: crate::vec::Vec::try_reserve #[stable(feature = "rust1", since = "1.0.0")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { default_read_to_end(self, buf, None) From 60f46289cf55759dc474d796edbf9d38cbab86d4 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 9 Oct 2023 14:32:15 +0100 Subject: [PATCH 371/676] Handle out of memory errors in fs::read/read_to_string --- library/std/src/fs.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c4a92927937a1..80d369eb067d4 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -260,7 +260,8 @@ pub fn read>(path: P) -> io::Result> { fn inner(path: &Path) -> io::Result> { let mut file = File::open(path)?; let size = file.metadata().map(|m| m.len() as usize).ok(); - let mut bytes = Vec::with_capacity(size.unwrap_or(0)); + let mut bytes = Vec::new(); + bytes.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; io::default_read_to_end(&mut file, &mut bytes, size)?; Ok(bytes) } @@ -302,7 +303,8 @@ pub fn read_to_string>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { let mut file = File::open(path)?; let size = file.metadata().map(|m| m.len() as usize).ok(); - let mut string = String::with_capacity(size.unwrap_or(0)); + let mut string = String::new(); + string.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; io::default_read_to_string(&mut file, &mut string, size)?; Ok(string) } @@ -774,14 +776,14 @@ impl Read for &File { // Reserves space in the buffer based on the file size when available. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let size = buffer_capacity_required(self); - buf.reserve(size.unwrap_or(0)); + buf.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; io::default_read_to_end(self, buf, size) } // Reserves space in the buffer based on the file size when available. fn read_to_string(&mut self, buf: &mut String) -> io::Result { let size = buffer_capacity_required(self); - buf.reserve(size.unwrap_or(0)); + buf.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; io::default_read_to_string(self, buf, size) } } From e11a6a9cacdae64f1ee6fd412af273931d3ef25a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 19 Dec 2023 00:42:58 +0000 Subject: [PATCH 372/676] No need to pass region bound pairs to resolve_regions_with_wf_tys --- .../rustc_hir_analysis/src/check/wfcheck.rs | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0978a5e65969a..0895cb5e771ce 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -10,10 +10,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; -use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs}; -use rustc_infer::infer::outlives::obligations::TypeOutlives; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_middle::mir::ConstraintCategory; use rustc_middle::query::Providers; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -731,10 +729,12 @@ fn ty_known_to_outlive<'tcx>( ty: Ty<'tcx>, region: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |infcx, region_bound_pairs| { - let origin = infer::RelateParamBound(DUMMY_SP, ty, None); - let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env); - outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation); + test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { + infcx.register_region_obligation(infer::RegionObligation { + sub_region: region, + sup_type: ty, + origin: infer::RelateParamBound(DUMMY_SP, ty, None), + }); }) } @@ -748,40 +748,32 @@ fn region_known_to_outlive<'tcx>( region_a: ty::Region<'tcx>, region_b: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |mut infcx, _| { - use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; - let origin = infer::RelateRegionParamBound(DUMMY_SP); - // `region_a: region_b` -> `region_b <= region_a` - infcx.push_sub_region_constraint( - origin, - region_b, - region_a, - ConstraintCategory::BoringNoLocation, - ); + test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { + infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP), region_b, region_a); }) } /// Given a known `param_env` and a set of well formed types, set up an /// `InferCtxt`, call the passed function (to e.g. set up region constraints /// to be tested), then resolve region and return errors -fn resolve_regions_with_wf_tys<'tcx>( +fn test_region_obligations<'tcx>( tcx: TyCtxt<'tcx>, id: LocalDefId, param_env: ty::ParamEnv<'tcx>, wf_tys: &FxIndexSet>, - add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>), + add_constraints: impl FnOnce(&InferCtxt<'tcx>), ) -> bool { // Unfortunately, we have to use a new `InferCtxt` each call, because // region constraints get added and solved there and we need to test each // call individually. let infcx = tcx.infer_ctxt().build(); + + add_constraints(&infcx); + let outlives_environment = OutlivesEnvironment::with_bounds( param_env, infcx.implied_bounds_tys(param_env, id, wf_tys), ); - let region_bound_pairs = outlives_environment.region_bound_pairs(); - - add_constraints(&infcx, region_bound_pairs); let errors = infcx.resolve_regions(&outlives_environment); debug!(?errors, "errors"); From 028d29301f9cbd174f3e21652d1c20d58af132ce Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 22:45:34 +0000 Subject: [PATCH 373/676] Deeply normalize when processing registered region obligations --- .../src/check/compare_impl_item.rs | 1 + .../src/check/compare_impl_item/refine.rs | 1 + .../rustc_hir_analysis/src/check/dropck.rs | 2 + .../rustc_hir_analysis/src/check/wfcheck.rs | 1 + .../src/infer/error_reporting/mod.rs | 11 +++++- .../src/infer/lexical_region_resolve/mod.rs | 5 ++- .../rustc_infer/src/infer/outlives/mod.rs | 16 ++++++-- .../src/infer/outlives/obligations.rs | 12 ++++-- compiler/rustc_trait_selection/src/lib.rs | 1 + compiler/rustc_trait_selection/src/regions.rs | 37 +++++++++++++++++++ .../src/traits/auto_trait.rs | 2 +- .../src/traits/coherence.rs | 1 + .../src/traits/engine.rs | 1 + .../rustc_trait_selection/src/traits/misc.rs | 1 + .../rustc_trait_selection/src/traits/mod.rs | 1 + .../next-solver/specialization-transmute.rs | 1 + .../specialization-transmute.stderr | 8 ++-- 17 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/regions.rs diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 479421af77fef..379c1154e5f26 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -20,6 +20,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericParamDefKind, TyCtxt}; use rustc_span::Span; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{ diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 6d2ebb150b957..3d3b21eabb383 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::Span; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{ elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt, }; diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 9fe95487bb9e0..3d2d667763a4c 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -8,6 +8,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, TyCtxt}; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; use crate::errors; @@ -188,6 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => { format!("{b}: {a}", a = ty::Region::new_var(tcx, a)) } + RegionResolutionError::CannotNormalize(..) => todo!(), }; guar = Some( struct_span_code_err!( diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0895cb5e771ce..b9c9eec28139a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -24,6 +24,7 @@ use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::misc::{ type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e19177fccefd8..0630bb2f44bb3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -518,6 +518,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit(); } + + RegionResolutionError::CannotNormalize(ty, origin) => { + self.tcx + .dcx() + .struct_span_err(origin.span(), format!("cannot normalize `{ty}`")) + .emit(); + } } } } @@ -559,7 +566,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { RegionResolutionError::GenericBoundFailure(..) => true, RegionResolutionError::ConcreteFailure(..) | RegionResolutionError::SubSupConflict(..) - | RegionResolutionError::UpperBoundUniverseConflict(..) => false, + | RegionResolutionError::UpperBoundUniverseConflict(..) + | RegionResolutionError::CannotNormalize(..) => false, }; let mut errors = if errors.iter().all(|e| is_bound_failure(e)) { @@ -574,6 +582,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), + RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(), }); errors } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 0562c6ccfcf75..4a1169e68e087 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -98,6 +98,8 @@ pub enum RegionResolutionError<'tcx> { SubregionOrigin<'tcx>, // cause of the constraint Region<'tcx>, // the placeholder `'b` ), + + CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>), } impl<'tcx> RegionResolutionError<'tcx> { @@ -106,7 +108,8 @@ impl<'tcx> RegionResolutionError<'tcx> { RegionResolutionError::ConcreteFailure(origin, _, _) | RegionResolutionError::GenericBoundFailure(origin, _, _) | RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _) - | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) => origin, + | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) + | RegionResolutionError::CannotNormalize(_, origin) => origin, } } } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 6379f84aa252f..97ab2f32c40ad 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -5,7 +5,7 @@ use super::{InferCtxt, RegionResolutionError}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; use rustc_middle::traits::query::OutlivesBound; -use rustc_middle::ty; +use rustc_middle::ty::{self, Ty}; pub mod components; pub mod env; @@ -41,12 +41,22 @@ impl<'tcx> InferCtxt<'tcx> { /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. + /// + /// If you are in a crate that has access to `rustc_trai_selection`, + /// then it's probably better to use `resolve_regions_normalizing_outlives_obligations`, + /// which knows how to normalize registered region obligations. #[must_use] - pub fn resolve_regions( + pub fn resolve_regions_with_normalize( &self, outlives_env: &OutlivesEnvironment<'tcx>, + deeply_normalize_ty: impl Fn(Ty<'tcx>) -> Result, Ty<'tcx>>, ) -> Vec> { - self.process_registered_region_obligations(outlives_env); + match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) { + Ok(()) => {} + Err((ty, origin)) => { + return vec![RegionResolutionError::CannotNormalize(ty, origin)]; + } + }; let (var_infos, data) = { let mut inner = self.inner.borrow_mut(); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index d7a3bfcbc41b6..1621e323d2cae 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -123,15 +123,19 @@ impl<'tcx> InferCtxt<'tcx> { /// flow of the inferencer. The key point is that it is /// invoked after all type-inference variables have been bound -- /// right before lexical region resolution. - #[instrument(level = "debug", skip(self, outlives_env))] - pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) { + #[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))] + pub fn process_registered_region_obligations( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + mut deeply_normalize_ty: impl FnMut(Ty<'tcx>) -> Result, E>, + ) -> Result<(), (E, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); let my_region_obligations = self.take_registered_region_obligations(); for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { + let sup_type = deeply_normalize_ty(sup_type).map_err(|e| (e, origin.clone()))?; debug!(?sup_type, ?sub_region, ?origin); - let sup_type = self.resolve_vars_if_possible(sup_type); let outlives = &mut TypeOutlives::new( self, @@ -143,6 +147,8 @@ impl<'tcx> InferCtxt<'tcx> { let category = origin.to_constraint_category(); outlives.type_must_outlive(origin, sup_type, sub_region, category); } + + Ok(()) } } diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 995ed1e3b573b..5ec45212bc791 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -39,6 +39,7 @@ extern crate smallvec; pub mod errors; pub mod infer; +pub mod regions; pub mod solve; pub mod traits; diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs new file mode 100644 index 0000000000000..3c53da32d0a1b --- /dev/null +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -0,0 +1,37 @@ +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{InferCtxt, RegionResolutionError}; +use rustc_middle::traits::ObligationCause; + +pub trait InferCtxtRegionExt<'tcx> { + /// Resolve regions, using the deep normalizer to normalize any type-outlives + /// obligations in the process. This is in `rustc_trait_selection` because + /// we need to normalize. + /// + /// Prefer this method over `resolve_regions_with_normalize`, unless you are + /// doing something specific for normalization. + fn resolve_regions( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec>; +} + +impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { + fn resolve_regions( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec> { + self.resolve_regions(outlives_env, |ty| { + let ty = self.resolve_vars_if_possible(ty); + + if self.next_trait_solver() { + crate::solve::deeply_normalize( + self.at(&ObligationCause::dummy(), outlives_env.param_env), + ty, + ) + .map_err(|_| ty) + } else { + Ok(ty) + } + }) + } +} diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c43447585746a..87b68a8bd2d68 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } let outlives_env = OutlivesEnvironment::new(full_env); - infcx.process_registered_region_obligations(&outlives_env); + let _ = infcx.process_registered_region_obligations::(&outlives_env, |ty| Ok(ty)); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ecbb92ca5b996..c49185a52c7ef 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -6,6 +6,7 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; +use crate::regions::InferCtxtRegionExt; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::{deeply_normalize_for_diagnostics, inspect}; use crate::traits::engine::TraitEngineExt; diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 013a50f9fa1c8..caf950037fdfd 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use super::FulfillmentContext; use super::TraitEngine; +use crate::regions::InferCtxtRegionExt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::NormalizeExt; diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 0cd376fcbbdc8..93f9c2333f0c0 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -1,5 +1,6 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. +use crate::regions::InferCtxtRegionExt; use crate::traits::{self, ObligationCause, ObligationCtxt}; use hir::LangItem; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 080ad7bd549c8..a7f6021d57a96 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -25,6 +25,7 @@ pub mod wf; use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::{InferCtxt, TyCtxtInferExt}; +use crate::regions::InferCtxtRegionExt; use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_errors::ErrorGuaranteed; diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index ff25656a7ff59..e7de564877d09 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -1,4 +1,5 @@ // compile-flags: -Znext-solver +//~^ ERROR cannot normalize `::Id` #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index a5459165587ca..a1cf5b761e34f 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-transmute.rs:3:12 + --> $DIR/specialization-transmute.rs:4:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -8,12 +8,14 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default +error: cannot normalize `::Id` + error[E0282]: type annotations needed - --> $DIR/specialization-transmute.rs:13:23 + --> $DIR/specialization-transmute.rs:14:23 | LL | default type Id = T; | ^ cannot infer type for associated type `::Id` -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0282`. From fef38a6337c6acf14eb70bf013717f484aa57eec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 25 Dec 2023 21:37:29 +0000 Subject: [PATCH 374/676] Normalize caller bounds --- .../src/type_check/constraint_conversion.rs | 3 +- .../src/infer/outlives/obligations.rs | 28 ++++++++++++++++--- .../rustc_infer/src/infer/outlives/verify.rs | 10 +++---- compiler/rustc_infer/src/lib.rs | 1 + 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 21d8026e17089..02ef7357d6645 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -157,7 +157,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { tcx, region_bound_pairs, Some(implicit_region_bound), - param_env, + // FIXME(-Znext-solver): These bounds are not normalized! + param_env.caller_bounds(), ) .type_must_outlive(origin, t1, r2, constraint_category); } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 1621e323d2cae..bc66522a8b6c7 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,8 +68,9 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{GenericArgKind, ToPredicate}; +use rustc_span::DUMMY_SP; use smallvec::smallvec; use super::env::OutlivesEnvironment; @@ -131,6 +132,25 @@ impl<'tcx> InferCtxt<'tcx> { ) -> Result<(), (E, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); + let normalized_caller_bounds: Vec<_> = outlives_env + .param_env + .caller_bounds() + .iter() + .filter_map(|clause| { + let bound_clause = clause.kind(); + let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else { + return None; + }; + Some(deeply_normalize_ty(outlives.0).map(|ty| { + bound_clause + .rebind(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, outlives.1))) + .to_predicate(self.tcx) + })) + }) + // FIXME: How do we accurately report an error here :( + .try_collect() + .map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?; + let my_region_obligations = self.take_registered_region_obligations(); for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { @@ -142,7 +162,7 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx, outlives_env.region_bound_pairs(), None, - outlives_env.param_env, + &normalized_caller_bounds, ); let category = origin.to_constraint_category(); outlives.type_must_outlive(origin, sup_type, sub_region, category); @@ -196,7 +216,7 @@ where tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], ) -> Self { Self { delegate, @@ -205,7 +225,7 @@ where tcx, region_bound_pairs, implicit_region_bound, - param_env, + caller_bounds, ), } } diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 7a85268492b43..2ad8b6b98e3e8 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -23,7 +23,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> { /// Outside of borrowck the only way to prove `T: '?0` is by /// setting `'?0` to `'empty`. implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], } impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { @@ -31,9 +31,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], ) -> Self { - Self { tcx, region_bound_pairs, implicit_region_bound, param_env } + Self { tcx, region_bound_pairs, implicit_region_bound, caller_bounds } } #[instrument(level = "debug", skip(self))] @@ -219,8 +219,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // To start, collect bounds from user environment. Note that // parameter environments are already elaborated, so we don't // have to worry about that. - let c_b = self.param_env.caller_bounds(); - let param_bounds = self.collect_outlives_from_clause_list(erased_ty, c_b.into_iter()); + let param_bounds = + self.collect_outlives_from_clause_list(erased_ty, self.caller_bounds.iter().copied()); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 9e3de1825ed37..e2dd4b49e1a4b 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -21,6 +21,7 @@ #![feature(extend_one)] #![feature(let_chains)] #![feature(if_let_guard)] +#![feature(iterator_try_collect)] #![feature(min_specialization)] #![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc From dc050f6d5bb1cb9d7529b6d9881ad99d8ce6a20d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 22 Jan 2024 19:33:45 +0000 Subject: [PATCH 375/676] Add a test --- .../normalize-region-obligations.rs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/ui/traits/next-solver/normalize-region-obligations.rs diff --git a/tests/ui/traits/next-solver/normalize-region-obligations.rs b/tests/ui/traits/next-solver/normalize-region-obligations.rs new file mode 100644 index 0000000000000..13c86b630f60e --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-region-obligations.rs @@ -0,0 +1,22 @@ +// revisions: normalize_param_env normalize_obligation +// check-pass +// compile-flags: -Znext-solver + +trait Foo { + #[cfg(normalize_param_env)] + type Gat<'a> where ::Assoc: 'a; + #[cfg(normalize_obligation)] + type Gat<'a> where Self: 'a; +} + +trait Mirror { type Assoc: ?Sized; } +impl Mirror for T { type Assoc = T; } + +impl Foo for T { + #[cfg(normalize_param_env)] + type Gat<'a> = i32 where T: 'a; + #[cfg(normalize_obligation)] + type Gat<'a> = i32 where ::Assoc: 'a; +} + +fn main() {} From 720d7a7a03b9997644fe28a12a80a910b2652760 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 26 Jan 2024 19:18:14 +0000 Subject: [PATCH 376/676] Apply suggestions from review --- .../src/type_check/constraint_conversion.rs | 15 ++++++----- .../src/type_check/free_region_relations.rs | 10 +++++-- compiler/rustc_borrowck/src/type_check/mod.rs | 13 +++++++-- .../rustc_hir_analysis/src/check/dropck.rs | 2 +- .../rustc_infer/src/infer/outlives/mod.rs | 8 +++--- .../src/infer/outlives/obligations.rs | 23 +++++++++------- .../rustc_infer/src/infer/outlives/verify.rs | 27 ++++--------------- compiler/rustc_trait_selection/src/regions.rs | 7 +++-- .../src/traits/auto_trait.rs | 2 +- .../next-solver/unsound-region-obligation.rs | 13 +++++++++ .../unsound-region-obligation.stderr | 7 +++++ 11 files changed, 77 insertions(+), 50 deletions(-) create mode 100644 tests/ui/traits/next-solver/unsound-region-obligation.rs create mode 100644 tests/ui/traits/next-solver/unsound-region-obligation.stderr diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 02ef7357d6645..52559f9039b65 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -33,7 +33,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { /// our special inference variable there, we would mess that up. region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, - param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, category: ConstraintCategory<'tcx>, @@ -47,7 +47,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, - param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, category: ConstraintCategory<'tcx>, @@ -59,7 +59,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { universal_regions, region_bound_pairs, implicit_region_bound, - param_env, + known_type_outlives_obligations, locations, span, category, @@ -136,7 +136,11 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // Extract out various useful fields we'll need below. let ConstraintConversion { - tcx, region_bound_pairs, implicit_region_bound, param_env, .. + tcx, + region_bound_pairs, + implicit_region_bound, + known_type_outlives_obligations, + .. } = *self; let ty::OutlivesPredicate(k1, r2) = predicate; @@ -157,8 +161,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { tcx, region_bound_pairs, Some(implicit_region_bound), - // FIXME(-Znext-solver): These bounds are not normalized! - param_env.caller_bounds(), + known_type_outlives_obligations, ) .type_must_outlive(origin, t1, r2, constraint_category); } diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 011b5b760c23a..d518f54fd2533 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -45,12 +45,14 @@ type NormalizedInputsAndOutput<'tcx> = Vec>; pub(crate) struct CreateResult<'tcx> { pub(crate) universal_region_relations: Frozen>, pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>, + pub(crate) known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } pub(crate) fn create<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, universal_regions: &Rc>, constraints: &mut MirTypeckRegionConstraints<'tcx>, @@ -58,6 +60,7 @@ pub(crate) fn create<'tcx>( UniversalRegionRelationsBuilder { infcx, param_env, + known_type_outlives_obligations, implicit_region_bound, constraints, universal_regions: universal_regions.clone(), @@ -175,6 +178,7 @@ impl UniversalRegionRelations<'_> { struct UniversalRegionRelationsBuilder<'this, 'tcx> { infcx: &'this InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], universal_regions: Rc>, implicit_region_bound: ty::Region<'tcx>, constraints: &'this mut MirTypeckRegionConstraints<'tcx>, @@ -200,7 +204,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let defining_ty_def_id = self.universal_regions.defining_ty.def_id().expect_local(); let span = tcx.def_span(defining_ty_def_id); - // Insert the facts we know from the predicates. Why? Why not. + // Insert the `'a: 'b` we know from the predicates. + // This does not consider the type-outlives. let param_env = self.param_env; self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env)); @@ -308,6 +313,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { outlives: self.outlives.freeze(), inverse_outlives: self.inverse_outlives.freeze(), }), + known_type_outlives_obligations: self.known_type_outlives_obligations, region_bound_pairs: self.region_bound_pairs, normalized_inputs_and_output, } @@ -322,7 +328,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { &self.universal_regions, &self.region_bound_pairs, self.implicit_region_bound, - self.param_env, + self.known_type_outlives_obligations, Locations::All(span), span, ConstraintCategory::Internal, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 488dfc64cf6f0..59c4d9a6c78ca 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -152,9 +152,14 @@ pub(crate) fn type_check<'mir, 'tcx>( universal_region_relations, region_bound_pairs, normalized_inputs_and_output, + known_type_outlives_obligations, } = free_region_relations::create( infcx, param_env, + // FIXME(-Znext-solver): These are unnormalized. Normalize them. + infcx.tcx.arena.alloc_from_iter( + param_env.caller_bounds().iter().filter_map(|clause| clause.as_type_outlives_clause()), + ), implicit_region_bound, universal_regions, &mut constraints, @@ -176,6 +181,7 @@ pub(crate) fn type_check<'mir, 'tcx>( body, param_env, ®ion_bound_pairs, + known_type_outlives_obligations, implicit_region_bound, &mut borrowck_context, ); @@ -850,6 +856,7 @@ struct TypeChecker<'a, 'tcx> { /// all of the promoted items. user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -1000,6 +1007,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { body: &'a Body<'tcx>, param_env: ty::ParamEnv<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, ) -> Self { @@ -1010,6 +1018,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_type_annotations: &body.user_type_annotations, param_env, region_bound_pairs, + known_type_outlives_obligations, implicit_region_bound, borrowck_context, reported_errors: Default::default(), @@ -1127,7 +1136,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, - self.param_env, + self.known_type_outlives_obligations, locations, locations.span(self.body), category, @@ -2731,7 +2740,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, - self.param_env, + self.known_type_outlives_obligations, locations, DUMMY_SP, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 3d2d667763a4c..7b60457affa82 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -189,7 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => { format!("{b}: {a}", a = ty::Region::new_var(tcx, a)) } - RegionResolutionError::CannotNormalize(..) => todo!(), + RegionResolutionError::CannotNormalize(..) => unreachable!(), }; guar = Some( struct_span_code_err!( diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 97ab2f32c40ad..926e198b21915 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -1,7 +1,7 @@ //! Various code related to computing outlives relations. use self::env::OutlivesEnvironment; use super::region_constraints::RegionConstraintData; -use super::{InferCtxt, RegionResolutionError}; +use super::{InferCtxt, RegionResolutionError, SubregionOrigin}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; use rustc_middle::traits::query::OutlivesBound; @@ -42,14 +42,14 @@ impl<'tcx> InferCtxt<'tcx> { /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. /// - /// If you are in a crate that has access to `rustc_trai_selection`, - /// then it's probably better to use `resolve_regions_normalizing_outlives_obligations`, + /// If you are in a crate that has access to `rustc_trait_selection`, + /// then it's probably better to use `resolve_regions`, /// which knows how to normalize registered region obligations. #[must_use] pub fn resolve_regions_with_normalize( &self, outlives_env: &OutlivesEnvironment<'tcx>, - deeply_normalize_ty: impl Fn(Ty<'tcx>) -> Result, Ty<'tcx>>, + deeply_normalize_ty: impl Fn(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result, Ty<'tcx>>, ) -> Vec> { match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) { Ok(()) => {} diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index bc66522a8b6c7..b10bf98e8b50a 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,8 +68,8 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; +use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::ty::{GenericArgKind, ToPredicate}; use rustc_span::DUMMY_SP; use smallvec::smallvec; @@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> { pub fn process_registered_region_obligations( &self, outlives_env: &OutlivesEnvironment<'tcx>, - mut deeply_normalize_ty: impl FnMut(Ty<'tcx>) -> Result, E>, + mut deeply_normalize_ty: impl FnMut(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result, E>, ) -> Result<(), (E, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); @@ -141,20 +141,23 @@ impl<'tcx> InferCtxt<'tcx> { let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else { return None; }; - Some(deeply_normalize_ty(outlives.0).map(|ty| { - bound_clause - .rebind(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, outlives.1))) - .to_predicate(self.tcx) - })) + Some( + deeply_normalize_ty( + outlives.0, + SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP), + ) + .map(|ty| bound_clause.rebind(ty::OutlivesPredicate(ty, outlives.1))), + ) }) - // FIXME: How do we accurately report an error here :( + // FIXME(-Znext-solver): How do we accurately report an error here :( .try_collect() .map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?; let my_region_obligations = self.take_registered_region_obligations(); for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { - let sup_type = deeply_normalize_ty(sup_type).map_err(|e| (e, origin.clone()))?; + let sup_type = + deeply_normalize_ty(sup_type, origin.clone()).map_err(|e| (e, origin.clone()))?; debug!(?sup_type, ?sub_region, ?origin); let outlives = &mut TypeOutlives::new( @@ -216,7 +219,7 @@ where tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - caller_bounds: &'cx [ty::Clause<'tcx>], + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], ) -> Self { Self { delegate, diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 2ad8b6b98e3e8..5d2f51c689b95 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -23,7 +23,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> { /// Outside of borrowck the only way to prove `T: '?0` is by /// setting `'?0` to `'empty`. implicit_region_bound: Option>, - caller_bounds: &'cx [ty::Clause<'tcx>], + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], } impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { @@ -31,7 +31,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - caller_bounds: &'cx [ty::Clause<'tcx>], + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], ) -> Self { Self { tcx, region_bound_pairs, implicit_region_bound, caller_bounds } } @@ -219,8 +219,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // To start, collect bounds from user environment. Note that // parameter environments are already elaborated, so we don't // have to worry about that. - let param_bounds = - self.collect_outlives_from_clause_list(erased_ty, self.caller_bounds.iter().copied()); + let param_bounds = self.caller_bounds.iter().copied().filter(move |outlives_predicate| { + super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty) + }); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -307,22 +308,4 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { .filter_map(|p| p.no_bound_vars()) .map(|OutlivesPredicate(_, r)| r) } - - /// Searches through a predicate list for a predicate `T: 'a`. - /// - /// Careful: does not elaborate predicates, and just uses `==` - /// when comparing `ty` for equality, so `ty` must be something - /// that does not involve inference variables and where you - /// otherwise want a precise match. - fn collect_outlives_from_clause_list( - &self, - erased_ty: Ty<'tcx>, - clauses: impl Iterator>, - ) -> impl Iterator, ty::Region<'tcx>>>> - { - let tcx = self.tcx; - clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| { - super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty) - }) - } } diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index 3c53da32d0a1b..e8929f114e165 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -20,12 +20,15 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { &self, outlives_env: &OutlivesEnvironment<'tcx>, ) -> Vec> { - self.resolve_regions(outlives_env, |ty| { + self.resolve_regions_with_normalize(outlives_env, |ty, origin| { let ty = self.resolve_vars_if_possible(ty); if self.next_trait_solver() { crate::solve::deeply_normalize( - self.at(&ObligationCause::dummy(), outlives_env.param_env), + self.at( + &ObligationCause::dummy_with_span(origin.span()), + outlives_env.param_env, + ), ty, ) .map_err(|_| ty) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 87b68a8bd2d68..b258007787de9 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } let outlives_env = OutlivesEnvironment::new(full_env); - let _ = infcx.process_registered_region_obligations::(&outlives_env, |ty| Ok(ty)); + let _ = infcx.process_registered_region_obligations::(&outlives_env, |ty, _| Ok(ty)); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.rs b/tests/ui/traits/next-solver/unsound-region-obligation.rs new file mode 100644 index 0000000000000..b8bfa03538887 --- /dev/null +++ b/tests/ui/traits/next-solver/unsound-region-obligation.rs @@ -0,0 +1,13 @@ +//~ ERROR the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime +// compile-flags: -Znext-solver +// Regression test for rust-lang/trait-system-refactor-initiative#59 + +trait StaticTy { + type Item<'a>: 'static; +} + +impl StaticTy for () { + type Item<'a> = &'a (); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.stderr b/tests/ui/traits/next-solver/unsound-region-obligation.stderr new file mode 100644 index 0000000000000..518de7ea3e025 --- /dev/null +++ b/tests/ui/traits/next-solver/unsound-region-obligation.stderr @@ -0,0 +1,7 @@ +error[E0477]: the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime + | + = note: type must satisfy the static lifetime + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0477`. From 7bdf705dd72edb9febe527c580a476d5d5f2f992 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Mon, 29 Jan 2024 21:01:15 -0500 Subject: [PATCH 377/676] 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 0213c87e12460e8f7101f96cc5daf4c3d20d6b9f Mon Sep 17 00:00:00 2001 From: Yukang Date: Tue, 30 Jan 2024 10:18:52 +0800 Subject: [PATCH 378/676] limit the names_possiblilities to less than 3 Co-authored-by: Urgau <3616612+Urgau@users.noreply.github.com> --- compiler/rustc_lint/src/context/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 31205f2b2fd97..07efc98f1fbe5 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -279,7 +279,7 @@ pub(super) fn builtin( is_feature_cfg |= best_match == sym::feature; } else { - if !names_possibilities.is_empty() { + if !names_possibilities.is_empty() && names_possibilities.len() <= 3 { names_possibilities.sort(); for cfg_name in names_possibilities.iter() { db.span_suggestion( From f8d4b2a150eca2797feaf863618886ac8e9cc8db Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sun, 29 Oct 2023 23:08:49 +0000 Subject: [PATCH 379/676] 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 380/676] 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 381/676] 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 382/676] 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 383/676] 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 ad526d831e295facc198610a27350076aa5aa438 Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 30 Jan 2024 12:42:29 +0800 Subject: [PATCH 384/676] add missing potential_query_instability for keys and values in hashmap --- .../src/coverageinfo/mapgen.rs | 1 + .../src/assert_module_sources.rs | 1 + compiler/rustc_codegen_ssa/src/back/link.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 1 + compiler/rustc_lint/src/context.rs | 14 +++++----- .../rustc_lint/src/context/diagnostics.rs | 1 + .../src/traits/auto_trait.rs | 1 + library/std/src/collections/hash/map.rs | 3 +++ .../internal-lints/query_stability.rs | 13 ++++++++++ .../internal-lints/query_stability.stderr | 26 ++++++++++++++++++- 10 files changed, 55 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 6116a6fd222b3..b1ceb1d4dd56d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -403,6 +403,7 @@ fn codegenned_and_inlined_items(tcx: TyCtxt<'_>) -> DefIdSet { let mut result = items.clone(); for cgu in cgus { + #[allow(rustc::potential_query_instability)] for item in cgu.items().keys() { if let mir::mono::MonoItem::Fn(ref instance) = item { let did = instance.def_id(); diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index a1daadce958eb..61fe6b261c6a9 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -267,6 +267,7 @@ impl CguReuseTracker { fn check_expected_reuse(&self, sess: &Session) { if let Some(ref data) = self.data { + #[allow(rustc::potential_query_instability)] let mut keys = data.expected_reuse.keys().collect::>(); keys.sort_unstable(); for cgu_name in keys { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f098fc9cb5970..b29f71bfb9553 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -682,6 +682,7 @@ fn link_dwarf_object<'a>( } // Input rlibs contain .o/.dwo files from dependencies. + #[allow(rustc::potential_query_instability)] let input_rlibs = cg_results .crate_info .used_crate_source diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d00ae4db300be..7f13814b082bc 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1950,6 +1950,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let len = remaining_fields.len(); + #[allow(rustc::potential_query_instability)] let mut displayable_field_names: Vec<&str> = remaining_fields.keys().map(|ident| ident.as_str()).collect(); // sorting &str primitives here, sort_unstable is ok diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 04201a38c35ea..1c480ec8f53b1 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -326,11 +326,9 @@ impl LintStore { /// True if this symbol represents a lint group name. pub fn is_lint_group(&self, lint_name: Symbol) -> bool { - debug!( - "is_lint_group(lint_name={:?}, lint_groups={:?})", - lint_name, - self.lint_groups.keys().collect::>() - ); + #[allow(rustc::potential_query_instability)] + let lint_groups = self.lint_groups.keys().collect::>(); + debug!("is_lint_group(lint_name={:?}, lint_groups={:?})", lint_name, lint_groups); let lint_name_str = lint_name.as_str(); self.lint_groups.contains_key(lint_name_str) || { let warnings_name_str = crate::WARNINGS.name_lower(); @@ -374,8 +372,12 @@ impl LintStore { None => { // 1. The tool is currently running, so this lint really doesn't exist. // FIXME: should this handle tools that never register a lint, like rustfmt? - debug!("lints={:?}", self.by_name.keys().collect::>()); + #[allow(rustc::potential_query_instability)] + let lints = self.by_name.keys().collect::>(); + debug!("lints={:?}", lints); let tool_prefix = format!("{tool_name}::"); + + #[allow(rustc::potential_query_instability)] return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) { self.no_lint_suggestion(&complete_name, tool_name.as_str()) } else { diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 312874db3f54e..eb42730f69a4d 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -185,6 +185,7 @@ pub(super) fn builtin( db.note("see the asm section of Rust By Example for more information"); } BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => { + #[allow(rustc::potential_query_instability)] let possibilities: Vec = sess.parse_sess.check_config.expecteds.keys().copied().collect(); let is_from_cargo = std::env::var_os("CARGO").is_some(); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c43447585746a..0b9fb7b6fbc1d 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -513,6 +513,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } while !vid_map.is_empty() { + #[allow(rustc::potential_query_instability)] let target = *vid_map.keys().next().expect("Keys somehow empty"); let deps = vid_map.remove(&target).expect("Entry somehow missing"); diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index fc27b6a67bfcb..0d4c1fa05cc87 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -356,6 +356,7 @@ impl HashMap { /// /// In the current implementation, iterating over keys takes O(capacity) time /// instead of O(len) because it internally visits empty buckets too. + #[rustc_lint_query_instability] #[stable(feature = "rust1", since = "1.0.0")] pub fn keys(&self) -> Keys<'_, K, V> { Keys { inner: self.iter() } @@ -417,6 +418,7 @@ impl HashMap { /// /// In the current implementation, iterating over values takes O(capacity) time /// instead of O(len) because it internally visits empty buckets too. + #[rustc_lint_query_instability] #[stable(feature = "rust1", since = "1.0.0")] pub fn values(&self) -> Values<'_, K, V> { Values { inner: self.iter() } @@ -449,6 +451,7 @@ impl HashMap { /// /// In the current implementation, iterating over values takes O(capacity) time /// instead of O(len) because it internally visits empty buckets too. + #[rustc_lint_query_instability] #[stable(feature = "map_values_mut", since = "1.10.0")] pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { ValuesMut { inner: self.iter_mut() } diff --git a/tests/ui-fulldeps/internal-lints/query_stability.rs b/tests/ui-fulldeps/internal-lints/query_stability.rs index 560675b448608..627ffa5cbd0f3 100644 --- a/tests/ui-fulldeps/internal-lints/query_stability.rs +++ b/tests/ui-fulldeps/internal-lints/query_stability.rs @@ -21,4 +21,17 @@ fn main() { for _ in x {} //~^ ERROR using `into_iter` + + let x = FxHashMap::::default(); + let _ = x.keys(); + //~^ ERROR using `keys` can result in unstable query results + + let _ = x.values(); + //~^ ERROR using `values` can result in unstable query results + + let mut x = FxHashMap::::default(); + for val in x.values_mut() { + //~^ ERROR using `values_mut` can result in unstable query results + *val = *val + 10; + } } diff --git a/tests/ui-fulldeps/internal-lints/query_stability.stderr b/tests/ui-fulldeps/internal-lints/query_stability.stderr index ee4ef9982371e..43b156dc20a3c 100644 --- a/tests/ui-fulldeps/internal-lints/query_stability.stderr +++ b/tests/ui-fulldeps/internal-lints/query_stability.stderr @@ -35,5 +35,29 @@ LL | for _ in x {} | = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale -error: aborting due to 4 previous errors +error: using `keys` can result in unstable query results + --> $DIR/query_stability.rs:26:15 + | +LL | let _ = x.keys(); + | ^^^^ + | + = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale + +error: using `values` can result in unstable query results + --> $DIR/query_stability.rs:29:15 + | +LL | let _ = x.values(); + | ^^^^^^ + | + = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale + +error: using `values_mut` can result in unstable query results + --> $DIR/query_stability.rs:33:18 + | +LL | for val in x.values_mut() { + | ^^^^^^^^^^ + | + = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale + +error: aborting due to 7 previous errors From ab8b66166775362dbeb25c8f8898f8760baaf123 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 30 Jan 2024 03:40:53 +0000 Subject: [PATCH 385/676] 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 386/676] 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 5350edb9e8f4e194a2cad9a41b81d97a8ed52fab Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 15:27:16 +1100 Subject: [PATCH 387/676] Remove the lifetime from `DiagnosticArgValue`. Because it's almost always static. This makes `impl IntoDiagnosticArg for DiagnosticArgValue` trivial, which is nice. There are a few diagnostics constructed in `compiler/rustc_mir_build/src/check_unsafety.rs` and `compiler/rustc_mir_transform/src/errors.rs` that now need symbols converted to `String` with `to_string` instead of `&str` with `as_str`, but that' no big deal, and worth it for the simplifications elsewhere. --- .../src/diagnostics/region_name.rs | 2 +- compiler/rustc_codegen_gcc/src/errors.rs | 2 +- .../src/assert_module_sources.rs | 2 +- compiler/rustc_codegen_ssa/src/back/write.rs | 4 +- compiler/rustc_codegen_ssa/src/errors.rs | 4 +- .../rustc_const_eval/src/const_eval/error.rs | 2 +- compiler/rustc_const_eval/src/errors.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 32 ++++------ compiler/rustc_errors/src/diagnostic_impls.rs | 60 +++++++++---------- compiler/rustc_errors/src/translation.rs | 6 +- compiler/rustc_hir_typeck/src/errors.rs | 2 +- compiler/rustc_infer/src/errors/mod.rs | 2 +- .../src/errors/note_and_explain.rs | 4 +- .../src/infer/error_reporting/mod.rs | 2 +- .../infer/error_reporting/need_type_info.rs | 2 +- .../nice_region_error/placeholder_error.rs | 2 +- compiler/rustc_metadata/src/locator.rs | 2 +- compiler/rustc_middle/src/error.rs | 7 +-- .../rustc_middle/src/mir/interpret/error.rs | 11 ++-- compiler/rustc_middle/src/mir/terminator.rs | 2 +- compiler/rustc_middle/src/thir.rs | 2 +- compiler/rustc_middle/src/ty/consts/int.rs | 2 +- compiler/rustc_middle/src/ty/consts/kind.rs | 2 +- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- compiler/rustc_middle/src/ty/generic_args.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- compiler/rustc_middle/src/ty/sty.rs | 8 +-- .../rustc_mir_build/src/check_unsafety.rs | 21 +++++-- compiler/rustc_mir_build/src/errors.rs | 12 ++-- .../rustc_mir_transform/src/const_prop.rs | 2 +- compiler/rustc_mir_transform/src/errors.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_session/src/config.rs | 2 +- compiler/rustc_session/src/session.rs | 2 +- src/tools/miri/src/diagnostics.rs | 2 +- 38 files changed, 113 insertions(+), 116 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 4cb49362863fc..15e1066e983a9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -188,7 +188,7 @@ impl Display for RegionName { } impl rustc_errors::IntoDiagnosticArg for RegionName { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index e9283b1989453..cc0fbe46dcc11 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -35,7 +35,7 @@ pub(crate) enum PossibleFeature<'a> { struct ExitCode(Option); impl IntoDiagnosticArg for ExitCode { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { let ExitCode(exit_code) = self; match exit_code { Some(t) => t.into_diagnostic_arg(), diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index a1daadce958eb..ad5a74b04e447 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -206,7 +206,7 @@ impl fmt::Display for CguReuse { } impl IntoDiagnosticArg for CguReuse { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(self.to_string())) } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index b13d566b40b3b..affd386361c09 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -999,7 +999,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>; struct Diagnostic { msgs: Vec<(DiagnosticMessage, Style)>, - args: FxHashMap, rustc_errors::DiagnosticArgValue<'static>>, + args: FxHashMap, rustc_errors::DiagnosticArgValue>, code: Option, lvl: Level, } @@ -1811,7 +1811,7 @@ impl Translate for SharedEmitter { impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { - let args: FxHashMap, rustc_errors::DiagnosticArgValue<'_>> = + let args: FxHashMap, rustc_errors::DiagnosticArgValue> = 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_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index ef291ead190cc..06ea5b9e8f4ab 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -147,7 +147,7 @@ impl<'a> CopyPath<'a> { struct DebugArgPath<'a>(pub &'a Path); impl IntoDiagnosticArg for DebugArgPath<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self.0))) } } @@ -974,7 +974,7 @@ pub enum ExpectedPointerMutability { } impl IntoDiagnosticArg for ExpectedPointerMutability { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { match self { ExpectedPointerMutability::Mut => DiagnosticArgValue::Str(Cow::Borrowed("*mut")), ExpectedPointerMutability::Not => DiagnosticArgValue::Str(Cow::Borrowed("*_")), diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index e8d0430c9d955..dabf78ef90e5f 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -34,7 +34,7 @@ impl MachineStopType for ConstEvalErrKind { } fn add_args( self: Box, - adder: &mut dyn FnMut(std::borrow::Cow<'static, str>, DiagnosticArgValue<'static>), + adder: &mut dyn FnMut(std::borrow::Cow<'static, str>, DiagnosticArgValue), ) { use ConstEvalErrKind::*; match *self { diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 9e27c19e94cd9..4d2b1ba3eec89 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -906,7 +906,7 @@ impl ReportErrorExt for ResourceExhaustionInfo { } impl rustc_errors::IntoDiagnosticArg for InternKind { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Borrowed(match self { InternKind::Static(Mutability::Not) => "static", InternKind::Static(Mutability::Mut) => "static_mut", diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 8a32e29ddc9dc..b3a4e1c5843dd 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -24,7 +24,7 @@ pub struct SuggestionsDisabled; /// `DiagnosticArg` are converted to `FluentArgs` (consuming the collection) at the start of /// diagnostic emission. pub type DiagnosticArg<'iter, 'source> = - (&'iter DiagnosticArgName<'source>, &'iter DiagnosticArgValue<'source>); + (&'iter DiagnosticArgName<'source>, &'iter DiagnosticArgValue); /// Name of a diagnostic argument. pub type DiagnosticArgName<'source> = Cow<'source, str>; @@ -32,10 +32,10 @@ pub type DiagnosticArgName<'source> = Cow<'source, str>; /// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted /// to a `FluentValue` by the emitter to be used in diagnostic translation. #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] -pub enum DiagnosticArgValue<'source> { - Str(Cow<'source, str>), +pub enum DiagnosticArgValue { + Str(Cow<'static, str>), Number(i128), - StrListSepByAnd(Vec>), + StrListSepByAnd(Vec>), } /// Converts a value of a type into a `DiagnosticArg` (typically a field of an `IntoDiagnostic` @@ -43,23 +43,17 @@ pub enum DiagnosticArgValue<'source> { /// being converted rather than on `DiagnosticArgValue`, which enables types from other `rustc_*` /// crates to implement this. pub trait IntoDiagnosticArg { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>; + fn into_diagnostic_arg(self) -> DiagnosticArgValue; } -impl<'source> IntoDiagnosticArg for DiagnosticArgValue<'source> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - match self { - DiagnosticArgValue::Str(s) => DiagnosticArgValue::Str(Cow::Owned(s.into_owned())), - DiagnosticArgValue::Number(n) => DiagnosticArgValue::Number(n), - DiagnosticArgValue::StrListSepByAnd(l) => DiagnosticArgValue::StrListSepByAnd( - l.into_iter().map(|s| Cow::Owned(s.into_owned())).collect(), - ), - } +impl IntoDiagnosticArg for DiagnosticArgValue { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { + self } } -impl<'source> Into> for DiagnosticArgValue<'source> { - fn into(self) -> FluentValue<'source> { +impl Into> for DiagnosticArgValue { + fn into(self) -> FluentValue<'static> { match self { DiagnosticArgValue::Str(s) => From::from(s), DiagnosticArgValue::Number(n) => From::from(n), @@ -109,7 +103,7 @@ pub struct Diagnostic { pub span: MultiSpan, pub children: Vec, pub suggestions: Result, SuggestionsDisabled>, - args: FxHashMap, DiagnosticArgValue<'static>>, + args: FxHashMap, DiagnosticArgValue>, /// This is not used for highlighting or rendering any error message. Rather, it can be used /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of @@ -931,7 +925,7 @@ impl Diagnostic { pub fn replace_args( &mut self, - args: FxHashMap, DiagnosticArgValue<'static>>, + args: FxHashMap, DiagnosticArgValue>, ) { self.args = args; } @@ -990,7 +984,7 @@ impl Diagnostic { ) -> ( &Level, &[(DiagnosticMessage, Style)], - Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>, + Vec<(&Cow<'static, str>, &DiagnosticArgValue)>, &Option, &Option, &MultiSpan, diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index df3fd4af4b436..faab3fc663a82 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -23,7 +23,7 @@ use std::process::ExitStatus; pub struct DiagnosticArgFromDisplay<'a>(pub &'a dyn fmt::Display); impl IntoDiagnosticArg for DiagnosticArgFromDisplay<'_> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.0.to_string().into_diagnostic_arg() } } @@ -41,7 +41,7 @@ impl<'a, T: fmt::Display> From<&'a T> for DiagnosticArgFromDisplay<'a> { } impl<'a, T: Clone + IntoDiagnosticArg> IntoDiagnosticArg for &'a T { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.clone().into_diagnostic_arg() } } @@ -50,7 +50,7 @@ macro_rules! into_diagnostic_arg_using_display { ($( $ty:ty ),+ $(,)?) => { $( impl IntoDiagnosticArg for $ty { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } @@ -62,7 +62,7 @@ macro_rules! into_diagnostic_arg_for_number { ($( $ty:ty ),+ $(,)?) => { $( impl IntoDiagnosticArg for $ty { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + 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 @@ -99,7 +99,7 @@ into_diagnostic_arg_using_display!( into_diagnostic_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); impl IntoDiagnosticArg for bool { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { if self { DiagnosticArgValue::Str(Cow::Borrowed("true")) } else { @@ -109,13 +109,13 @@ impl IntoDiagnosticArg for bool { } impl IntoDiagnosticArg for char { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}"))) } } impl IntoDiagnosticArg for Vec { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::StrListSepByAnd( self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(), ) @@ -123,49 +123,49 @@ impl IntoDiagnosticArg for Vec { } impl IntoDiagnosticArg for Symbol { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_ident_string().into_diagnostic_arg() } } impl<'a> IntoDiagnosticArg for &'a str { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } impl IntoDiagnosticArg for String { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(self)) } } impl<'a> IntoDiagnosticArg for Cow<'a, str> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(self.into_owned())) } } impl<'a> IntoDiagnosticArg for &'a Path { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(self.display().to_string())) } } impl IntoDiagnosticArg for PathBuf { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(self.display().to_string())) } } impl IntoDiagnosticArg for PanicStrategy { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string())) } } impl IntoDiagnosticArg for hir::ConstContext { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Borrowed(match self { hir::ConstContext::ConstFn => "const_fn", hir::ConstContext::Static(_) => "static", @@ -175,49 +175,49 @@ impl IntoDiagnosticArg for hir::ConstContext { } impl IntoDiagnosticArg for ast::Expr { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(pprust::expr_to_string(&self))) } } impl IntoDiagnosticArg for ast::Path { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(&self))) } } impl IntoDiagnosticArg for ast::token::Token { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(pprust::token_to_string(&self)) } } impl IntoDiagnosticArg for ast::token::TokenKind { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(pprust::token_kind_to_string(&self)) } } impl IntoDiagnosticArg for type_ir::FloatTy { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Borrowed(self.name_str())) } } impl IntoDiagnosticArg for std::ffi::CString { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) } } impl IntoDiagnosticArg for rustc_data_structures::small_c_str::SmallCStr { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) } } impl IntoDiagnosticArg for ast::Visibility { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { let s = pprust::vis_to_string(&self); let s = s.trim_end().to_string(); DiagnosticArgValue::Str(Cow::Owned(s)) @@ -225,7 +225,7 @@ impl IntoDiagnosticArg for ast::Visibility { } impl IntoDiagnosticArg for rustc_lint_defs::Level { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag())) } } @@ -240,7 +240,7 @@ impl From> for DiagnosticSymbolList { } impl IntoDiagnosticArg for DiagnosticSymbolList { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::StrListSepByAnd( self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(), ) @@ -248,7 +248,7 @@ impl IntoDiagnosticArg for DiagnosticSymbolList { } impl IntoDiagnosticArg for hir::def::Res { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Borrowed(self.descr())) } } @@ -334,13 +334,13 @@ pub struct DelayedAtWithoutNewline { } impl IntoDiagnosticArg for DiagnosticLocation { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::from(self.to_string())) } } impl IntoDiagnosticArg for Backtrace { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::from(self.to_string())) } } @@ -353,7 +353,7 @@ pub struct InvalidFlushedDelayedDiagnosticLevel { pub level: Level, } impl IntoDiagnosticArg for Level { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::from(self.to_string())) } } @@ -368,7 +368,7 @@ pub struct IndicateAnonymousLifetime { } impl IntoDiagnosticArg for type_ir::ClosureKind { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(self.as_str().into()) } } diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index ed35eb1b6c4ad..af927bf9629a1 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -12,9 +12,9 @@ use std::error::Report; /// /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then /// passed around as a reference thereafter. -pub fn to_fluent_args<'iter, 'arg: 'iter>( - iter: impl Iterator>, -) -> FluentArgs<'arg> { +pub fn to_fluent_args<'iter>( + iter: impl Iterator>, +) -> FluentArgs<'static> { let mut args = if let Some(size) = iter.size_hint().1 { FluentArgs::with_capacity(size) } else { diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index b75cf4b4e8bca..0695af15b16f8 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -43,7 +43,7 @@ pub enum ReturnLikeStatementKind { } impl IntoDiagnosticArg for ReturnLikeStatementKind { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { let kind = match self { Self::Return => "return", Self::Become => "become", diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 4e9f573091b09..0a128218c9229 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -534,7 +534,7 @@ pub enum TyOrSig<'tcx> { } impl IntoDiagnosticArg for TyOrSig<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { match self { TyOrSig::Ty(ty) => ty.into_diagnostic_arg(), TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(), diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 8e45cc6d80e92..331e3633e908d 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -108,7 +108,7 @@ pub enum SuffixKind { } impl IntoDiagnosticArg for PrefixKind { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { let kind = match self { Self::Empty => "empty", Self::RefValidFor => "ref_valid_for", @@ -130,7 +130,7 @@ impl IntoDiagnosticArg for PrefixKind { } impl IntoDiagnosticArg for SuffixKind { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { let kind = match self { Self::Empty => "empty", Self::Continues => "continues", diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e19177fccefd8..db01b5bd70719 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2914,7 +2914,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>); impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { use crate::traits::ObligationCauseCode::*; let kind = match self.0.code() { CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat", diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index cf1e042c529a4..7287fc26053fe 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -134,7 +134,7 @@ impl InferenceDiagnosticsParentData { } impl IntoDiagnosticArg for UnderspecifiedArgKind { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { let kind = match self { Self::Type { .. } => "type", Self::Const { is_parameter: true } => "const_with_param", diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index e1a83c86318e9..b3b83c8ab957f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -30,7 +30,7 @@ impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T> where T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { rustc_errors::DiagnosticArgValue::Str(self.to_string().into()) } } diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 2376d95334155..1ab965e28769f 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -291,7 +291,7 @@ impl fmt::Display for CrateFlavor { } impl IntoDiagnosticArg for CrateFlavor { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { match self { CrateFlavor::Rlib => DiagnosticArgValue::Str(Cow::Borrowed("rlib")), CrateFlavor::Rmeta => DiagnosticArgValue::Str(Cow::Borrowed("rmeta")), diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index e0436b38c4be6..211da80020297 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -95,17 +95,14 @@ pub(super) struct ConstNotUsedTraitAlias { pub struct CustomSubdiagnostic<'a> { pub msg: fn() -> DiagnosticMessage, - pub add_args: - Box, DiagnosticArgValue<'static>)) + 'a>, + pub add_args: Box, DiagnosticArgValue)) + 'a>, } impl<'a> CustomSubdiagnostic<'a> { pub fn label(x: fn() -> DiagnosticMessage) -> Self { Self::label_and_then(x, |_| {}) } - pub fn label_and_then< - F: FnOnce(&mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>)) + 'a, - >( + pub fn label_and_then, DiagnosticArgValue)) + 'a>( 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 7a1df4954514a..95574aee499f2 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -233,7 +233,7 @@ pub enum InvalidMetaKind { } impl IntoDiagnosticArg for InvalidMetaKind { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Borrowed(match self { InvalidMetaKind::SliceTooBig => "slice_too_big", InvalidMetaKind::TooBig => "too_big", @@ -267,7 +267,7 @@ pub struct Misalignment { macro_rules! impl_into_diagnostic_arg_through_debug { ($($ty:ty),*$(,)?) => {$( impl IntoDiagnosticArg for $ty { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}"))) } } @@ -367,7 +367,7 @@ pub enum PointerKind { } impl IntoDiagnosticArg for PointerKind { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str( match self { Self::Ref => "ref", @@ -485,10 +485,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<'static>), - ); + fn add_args(self: Box, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue)); } impl dyn MachineStopType { diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index fdbbf468ecea2..0fe33e441f430 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<'static>)) + pub fn add_args(self, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue)) where O: fmt::Debug, { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index b4b8387c262b9..0fed4ccc62a83 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -674,7 +674,7 @@ impl<'tcx> Pat<'tcx> { } impl<'tcx> IntoDiagnosticArg for Pat<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { format!("{self}").into_diagnostic_arg() } } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 310cf113b11b6..f7c33960fdd83 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -117,7 +117,7 @@ impl std::fmt::Debug for ConstInt { impl IntoDiagnosticArg for ConstInt { // FIXME this simply uses the Debug impl, but we could probably do better by converting both // to an inherent method that returns `Cow`. - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(format!("{self:?}").into()) } } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 16e7b16a0bf8c..603d7f46aabe0 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -15,7 +15,7 @@ pub struct UnevaluatedConst<'tcx> { } impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { format!("{self:?}").into_diagnostic_arg() } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index c1e2479defd0a..8678f388298c2 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -20,7 +20,7 @@ use rustc_span::{BytePos, Span}; use rustc_type_ir::TyKind::*; impl<'tcx> IntoDiagnosticArg for Ty<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 5a4b86eeffd76..69ad6810c6fe0 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -56,7 +56,7 @@ unsafe impl<'tcx> Sync for GenericArg<'tcx> where } impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 25473f52c039e..f07a4ac29e961 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -269,7 +269,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { } impl<'tcx> IntoDiagnosticArg for LayoutError<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dac60ae58a0ca..dabd50a32b95c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -583,13 +583,13 @@ impl<'tcx> Predicate<'tcx> { } impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + 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<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 73052be30ae3d..bac5068a69b86 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2632,7 +2632,7 @@ where pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintOnlyTraitPath<'tcx> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } @@ -2649,7 +2649,7 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintSugared<'tcx> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b089f4a9e78b9..43a6281481fa4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -862,7 +862,7 @@ impl<'tcx> PolyTraitRef<'tcx> { } impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } @@ -908,7 +908,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> { } impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } @@ -1149,7 +1149,7 @@ impl<'tcx, T> IntoDiagnosticArg for Binder<'tcx, T> where T: IntoDiagnosticArg, { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.value.into_diagnostic_arg() } } @@ -1359,7 +1359,7 @@ impl<'tcx> FnSig<'tcx> { } impl<'tcx> IntoDiagnosticArg for FnSig<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index ac147afaab313..226df08ff8f68 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -698,12 +698,15 @@ impl UnsafeOpKind { span, function: &with_no_trimmed_paths!(tcx.def_path_str(*function)), missing_target_features: DiagnosticArgValue::StrListSepByAnd( - missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), ), missing_target_features_count: missing.len(), note: if build_enabled.is_empty() { None } else { Some(()) }, build_target_features: DiagnosticArgValue::StrListSepByAnd( - build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + build_enabled + .iter() + .map(|feature| Cow::from(feature.to_string())) + .collect(), ), build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, @@ -860,12 +863,15 @@ impl UnsafeOpKind { dcx.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, missing_target_features: DiagnosticArgValue::StrListSepByAnd( - missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), ), missing_target_features_count: missing.len(), note: if build_enabled.is_empty() { None } else { Some(()) }, build_target_features: DiagnosticArgValue::StrListSepByAnd( - build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + build_enabled + .iter() + .map(|feature| Cow::from(feature.to_string())) + .collect(), ), build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, @@ -876,12 +882,15 @@ impl UnsafeOpKind { dcx.emit_err(CallToFunctionWithRequiresUnsafe { span, missing_target_features: DiagnosticArgValue::StrListSepByAnd( - missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), ), missing_target_features_count: missing.len(), note: if build_enabled.is_empty() { None } else { Some(()) }, build_target_features: DiagnosticArgValue::StrListSepByAnd( - build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + build_enabled + .iter() + .map(|feature| Cow::from(feature.to_string())) + .collect(), ), build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 6929c8040c503..147001cabb0f3 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -127,11 +127,11 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, - pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features: DiagnosticArgValue, pub missing_target_features_count: usize, #[note] pub note: Option<()>, - pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features: DiagnosticArgValue, pub build_target_features_count: usize, #[subdiagnostic] pub unsafe_not_inherited_note: Option, @@ -379,11 +379,11 @@ pub struct CallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, - pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features: DiagnosticArgValue, pub missing_target_features_count: usize, #[note] pub note: Option<()>, - pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features: DiagnosticArgValue, pub build_target_features_count: usize, #[subdiagnostic] pub unsafe_not_inherited_note: Option, @@ -397,11 +397,11 @@ pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[label] pub span: Span, pub function: &'a str, - pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features: DiagnosticArgValue, pub missing_target_features_count: usize, #[note] pub note: Option<()>, - pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features: DiagnosticArgValue, pub build_target_features_count: usize, #[subdiagnostic] pub unsafe_not_inherited_note: Option, diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 8b9e507c8c746..c49f92f4f859f 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<'static>), + _: &mut dyn FnMut(std::borrow::Cow<'static, str>, rustc_errors::DiagnosticArgValue), ) {} } throw_machine_stop!(Zst) diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 4ef3d47d6a6f5..30de40e226c33 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -125,7 +125,7 @@ impl RequiresUnsafeDetail { diag.arg( "missing_target_features", DiagnosticArgValue::StrListSepByAnd( - missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), ), ); diag.arg("missing_target_features_count", missing.len()); @@ -136,7 +136,7 @@ impl RequiresUnsafeDetail { DiagnosticArgValue::StrListSepByAnd( build_enabled .iter() - .map(|feature| Cow::from(feature.as_str())) + .map(|feature| Cow::from(feature.to_string())) .collect(), ), ); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9d9741bbe8947..8f27d01794cc6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -78,7 +78,7 @@ pub(crate) enum ProcMacroKind { } impl IntoDiagnosticArg for ProcMacroKind { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { match self { ProcMacroKind::Attribute => "attribute proc macro", ProcMacroKind::Derive => "derive proc macro", diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0743ff0386402..9788fcb3c7d36 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -90,7 +90,7 @@ impl PatternSource { } impl IntoDiagnosticArg for PatternSource { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::Borrowed(self.descr())) } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 2ec1a726cef1f..d35f951e2aea3 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3092,7 +3092,7 @@ impl fmt::Display for CrateType { } impl IntoDiagnosticArg for CrateType { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 7cd76ad729388..3a0ae74dd9215 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -111,7 +111,7 @@ impl Mul for Limit { } impl rustc_errors::IntoDiagnosticArg for Limit { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { self.to_string().into_diagnostic_arg() } } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index bf3284df5967a..92c58d48dc757 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -104,7 +104,7 @@ impl MachineStopType for TerminationInfo { self: Box, _: &mut dyn FnMut( std::borrow::Cow<'static, str>, - rustc_errors::DiagnosticArgValue<'static>, + rustc_errors::DiagnosticArgValue, ), ) { } From 45dc19785df0cd23af30498d3e1221e5e78142dc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 15:44:37 +1100 Subject: [PATCH 388/676] Remove lifetimes from some diagnostics. Because the `&'a str` fields can be trivially converted to `String` without causing any extra allocations. --- .../rustc_mir_build/src/check_unsafety.rs | 12 +++++----- compiler/rustc_mir_build/src/errors.rs | 24 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 226df08ff8f68..422549755d1e1 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -605,7 +605,7 @@ impl UnsafeOpKind { span, UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { span, - function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + function: with_no_trimmed_paths!(tcx.def_path_str(*did)), unsafe_not_inherited_note, }, ), @@ -696,7 +696,7 @@ impl UnsafeOpKind { span, UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { span, - function: &with_no_trimmed_paths!(tcx.def_path_str(*function)), + function: with_no_trimmed_paths!(tcx.def_path_str(*function)), missing_target_features: DiagnosticArgValue::StrListSepByAnd( missing.iter().map(|feature| Cow::from(feature.to_string())).collect(), ), @@ -750,14 +750,14 @@ impl UnsafeOpKind { dcx.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, unsafe_not_inherited_note, - function: &tcx.def_path_str(*did), + function: tcx.def_path_str(*did), }); } CallToUnsafeFunction(Some(did)) => { dcx.emit_err(CallToUnsafeFunctionRequiresUnsafe { span, unsafe_not_inherited_note, - function: &tcx.def_path_str(*did), + function: tcx.def_path_str(*did), }); } CallToUnsafeFunction(None) if unsafe_op_in_unsafe_fn_allowed => { @@ -875,7 +875,7 @@ impl UnsafeOpKind { ), build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, - function: &tcx.def_path_str(*function), + function: tcx.def_path_str(*function), }); } CallToFunctionWith { function, missing, build_enabled } => { @@ -894,7 +894,7 @@ impl UnsafeOpKind { ), build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, - function: &tcx.def_path_str(*function), + function: tcx.def_path_str(*function), }); } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 147001cabb0f3..3c1ba26a50309 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -23,10 +23,10 @@ pub struct UnconditionalRecursion { #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)] #[note] -pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { +pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { #[label] pub span: Span, - pub function: &'a str, + pub function: String, #[subdiagnostic] pub unsafe_not_inherited_note: Option, } @@ -123,10 +123,10 @@ pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)] #[help] -pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { +pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { #[label] pub span: Span, - pub function: &'a str, + pub function: String, pub missing_target_features: DiagnosticArgValue, pub missing_target_features_count: usize, #[note] @@ -140,11 +140,11 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { #[derive(Diagnostic)] #[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = E0133)] #[note] -pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { +pub struct CallToUnsafeFunctionRequiresUnsafe { #[primary_span] #[label] pub span: Span, - pub function: &'a str, + pub function: String, #[subdiagnostic] pub unsafe_not_inherited_note: Option, } @@ -163,11 +163,11 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNameless { #[derive(Diagnostic)] #[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] -pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { +pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, - pub function: &'a str, + pub function: String, #[subdiagnostic] pub unsafe_not_inherited_note: Option, } @@ -374,11 +374,11 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed #[derive(Diagnostic)] #[diag(mir_build_call_to_fn_with_requires_unsafe, code = E0133)] #[help] -pub struct CallToFunctionWithRequiresUnsafe<'a> { +pub struct CallToFunctionWithRequiresUnsafe { #[primary_span] #[label] pub span: Span, - pub function: &'a str, + pub function: String, pub missing_target_features: DiagnosticArgValue, pub missing_target_features_count: usize, #[note] @@ -392,11 +392,11 @@ pub struct CallToFunctionWithRequiresUnsafe<'a> { #[derive(Diagnostic)] #[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[help] -pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { +pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, - pub function: &'a str, + pub function: String, pub missing_target_features: DiagnosticArgValue, pub missing_target_features_count: usize, #[note] From 06aa381adbd5bac561c57dc6fc0390da8ec45b69 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 15:52:20 +1100 Subject: [PATCH 389/676] Remove `DiagnosticArgName` from `rustc_codegen_ssa`. It's identical to the one in `rustc_errors`; use that instead. Also remove some `rustc_errors::` qualifiers. --- compiler/rustc_codegen_ssa/src/back/write.rs | 17 +++++++++-------- compiler/rustc_errors/src/lib.rs | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index affd386361c09..562359a6b3976 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -14,8 +14,11 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; -use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level}; -use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, ErrCode, Style}; +use rustc_errors::translation::Translate; +use rustc_errors::{ + DiagCtxt, DiagnosticArgName, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrCode, + FatalError, FluentBundle, Level, Style, +}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ @@ -995,11 +998,9 @@ pub(crate) enum Message { /// process another codegen unit. pub struct CguMessage; -type DiagnosticArgName<'source> = Cow<'source, str>; - struct Diagnostic { msgs: Vec<(DiagnosticMessage, Style)>, - args: FxHashMap, rustc_errors::DiagnosticArgValue>, + args: FxHashMap, DiagnosticArgValue>, code: Option, lvl: Level, } @@ -1800,18 +1801,18 @@ impl SharedEmitter { } impl Translate for SharedEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn fluent_bundle(&self) -> Option<&Lrc> { None } - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { + fn fallback_fluent_bundle(&self) -> &FluentBundle { panic!("shared emitter attempted to translate a diagnostic"); } } impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { - let args: FxHashMap, rustc_errors::DiagnosticArgValue> = + let args: FxHashMap, DiagnosticArgValue> = 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_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 6d9208341a5c0..295112c7c3c42 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -33,8 +33,8 @@ extern crate self as rustc_errors; pub use codes::*; pub use diagnostic::{ - AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, - DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, + AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName, + DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; pub use diagnostic_builder::{ BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic, From f0426b77fc1f4bc170ababce990c88565310eb26 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 16:04:03 +1100 Subject: [PATCH 390/676] Remove the lifetime from `DiagnosticArgName`. Because it's always 'static. --- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 562359a6b3976..06edb79453727 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1000,7 +1000,7 @@ pub struct CguMessage; struct Diagnostic { msgs: Vec<(DiagnosticMessage, Style)>, - args: FxHashMap, DiagnosticArgValue>, + args: FxHashMap, code: Option, lvl: Level, } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index b3a4e1c5843dd..0ce20fda27ff5 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -23,11 +23,10 @@ pub struct SuggestionsDisabled; /// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of /// `DiagnosticArg` are converted to `FluentArgs` (consuming the collection) at the start of /// diagnostic emission. -pub type DiagnosticArg<'iter, 'source> = - (&'iter DiagnosticArgName<'source>, &'iter DiagnosticArgValue); +pub type DiagnosticArg<'iter, 'source> = (&'iter DiagnosticArgName, &'iter DiagnosticArgValue); /// Name of a diagnostic argument. -pub type DiagnosticArgName<'source> = Cow<'source, str>; +pub type DiagnosticArgName = Cow<'static, str>; /// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted /// to a `FluentValue` by the emitter to be used in diagnostic translation. @@ -103,7 +102,7 @@ pub struct Diagnostic { pub span: MultiSpan, pub children: Vec, pub suggestions: Result, SuggestionsDisabled>, - args: FxHashMap, DiagnosticArgValue>, + args: FxHashMap, /// This is not used for highlighting or rendering any error message. Rather, it can be used /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of @@ -923,10 +922,7 @@ impl Diagnostic { self } - pub fn replace_args( - &mut self, - args: FxHashMap, DiagnosticArgValue>, - ) { + pub fn replace_args(&mut self, args: FxHashMap) { self.args = args; } From 514a5d8d556a6e28f586551c31ad0e9c83224caf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 16:06:18 +1100 Subject: [PATCH 391/676] Remove the second lifetime from `DiagnosticArg`. Because it's always static. I'm surprised the compiler allowed this unused lifetime without any complaint. --- compiler/rustc_errors/src/diagnostic.rs | 4 ++-- compiler/rustc_errors/src/lib.rs | 4 ++-- compiler/rustc_errors/src/translation.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 0ce20fda27ff5..bf1ab37a1cf48 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -23,7 +23,7 @@ pub struct SuggestionsDisabled; /// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of /// `DiagnosticArg` are converted to `FluentArgs` (consuming the collection) at the start of /// diagnostic emission. -pub type DiagnosticArg<'iter, 'source> = (&'iter DiagnosticArgName, &'iter DiagnosticArgValue); +pub type DiagnosticArg<'iter> = (&'iter DiagnosticArgName, &'iter DiagnosticArgValue); /// Name of a diagnostic argument. pub type DiagnosticArgName = Cow<'static, str>; @@ -909,7 +909,7 @@ impl Diagnostic { // Exact iteration order of diagnostic arguments shouldn't make a difference to output because // they're only used in interpolation. #[allow(rustc::potential_query_instability)] - pub fn args(&self) -> impl Iterator> { + pub fn args(&self) -> impl Iterator> { self.args.iter() } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 295112c7c3c42..9090adea1562d 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -628,7 +628,7 @@ impl DiagCtxt { pub fn eagerly_translate<'a>( &self, message: DiagnosticMessage, - args: impl Iterator>, + args: impl Iterator>, ) -> SubdiagnosticMessage { SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args))) } @@ -637,7 +637,7 @@ impl DiagCtxt { pub fn eagerly_translate_to_string<'a>( &self, message: DiagnosticMessage, - args: impl Iterator>, + args: impl Iterator>, ) -> String { let inner = self.inner.borrow(); let args = crate::translation::to_fluent_args(args); diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index af927bf9629a1..5bdac367d55e7 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -13,7 +13,7 @@ use std::error::Report; /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then /// passed around as a reference thereafter. pub fn to_fluent_args<'iter>( - iter: impl Iterator>, + iter: impl Iterator>, ) -> FluentArgs<'static> { let mut args = if let Some(size) = iter.size_hint().1 { FluentArgs::with_capacity(size) From 5860763f1808ef7ba2628bf46c08e77c96804925 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 30 Jan 2024 09:51:28 +0100 Subject: [PATCH 392/676] 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 ca243e750118ae679c7c3413f21e5e772bf694da Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 30 Jan 2024 16:54:40 +0800 Subject: [PATCH 393/676] add testcase for more than 3 cfg names --- .../check-cfg/cfg-value-for-cfg-name-duplicate.rs | 12 ++++++++++++ .../cfg-value-for-cfg-name-duplicate.stderr | 13 +++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs create mode 100644 tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs new file mode 100644 index 0000000000000..a6e68e1b7101c --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs @@ -0,0 +1,12 @@ +// #120427 +// This test checks we won't suggest more than 3 span suggestions for cfg names +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(foo,values("value")) --check-cfg=cfg(bar,values("value")) --check-cfg=cfg(bee,values("value")) --check-cfg=cfg(cow,values("value")) + +#[cfg(value)] +//~^ WARNING unexpected `cfg` condition name: `value` +fn x() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr new file mode 100644 index 0000000000000..82d471d715b83 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr @@ -0,0 +1,13 @@ +warning: unexpected `cfg` condition name: `value` + --> $DIR/cfg-value-for-cfg-name-duplicate.rs:8:7 + | +LL | #[cfg(value)] + | ^^^^^ + | + = help: expected names are: `bar`, `bee`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(value)` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + From 64b6b5b6ce078684dea0d312e3ac0911e1d6a0df Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 25 Jan 2024 19:16:38 +0300 Subject: [PATCH 394/676] 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 395/676] 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 396/676] 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 397/676] 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 398/676] 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 399/676] 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 400/676] 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 401/676] 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 402/676] 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 403/676] `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 404/676] 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 405/676] 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 406/676] 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 407/676] 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 408/676] 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 409/676] 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 410/676] 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 411/676] 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 412/676] 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 413/676] 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 414/676] 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 415/676] 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 416/676] 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 d34b0fa495bfbc3bd7de14a691822706074fcbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 26 Jan 2024 18:57:58 +0000 Subject: [PATCH 417/676] Add test for method on unbounded type parameter receiver --- .../traits/method-on-unbounded-type-param.rs | 15 ++++ .../method-on-unbounded-type-param.stderr | 83 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 tests/ui/traits/method-on-unbounded-type-param.rs create mode 100644 tests/ui/traits/method-on-unbounded-type-param.stderr diff --git a/tests/ui/traits/method-on-unbounded-type-param.rs b/tests/ui/traits/method-on-unbounded-type-param.rs new file mode 100644 index 0000000000000..8505eb41e98bb --- /dev/null +++ b/tests/ui/traits/method-on-unbounded-type-param.rs @@ -0,0 +1,15 @@ +fn f(a: T, b: T) -> std::cmp::Ordering { + a.cmp(&b) //~ ERROR E0599 +} +fn g(a: T, b: T) -> std::cmp::Ordering { + (&a).cmp(&b) //~ ERROR E0599 +} +fn h(a: &T, b: T) -> std::cmp::Ordering { + a.cmp(&b) //~ ERROR E0599 +} +trait T {} +impl T for X {} +fn main() { + let x: Box = Box::new(0); + x.cmp(&x); //~ ERROR E0599 +} diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr new file mode 100644 index 0000000000000..0b650995de5c5 --- /dev/null +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -0,0 +1,83 @@ +error[E0599]: `T` is not an iterator + --> $DIR/method-on-unbounded-type-param.rs:2:7 + | +LL | fn f(a: T, b: T) -> std::cmp::Ordering { + | - method `cmp` not found for this type parameter +LL | a.cmp(&b) + | ^^^ `T` is not an iterator + | + = note: the following trait bounds were not satisfied: + `T: Iterator` + which is required by `&mut T: Iterator` +help: consider restricting the type parameter to satisfy the trait bound + | +LL | fn f(a: T, b: T) -> std::cmp::Ordering where T: Iterator { + | +++++++++++++++++ + +error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:5:10 + | +LL | (&a).cmp(&b) + | ^^^ method cannot be called on `&T` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `T: Ord` + which is required by `&T: Ord` + `&T: Iterator` + which is required by `&mut &T: Iterator` + `T: Iterator` + which is required by `&mut T: Iterator` +help: consider restricting the type parameters to satisfy the trait bounds + | +LL | fn g(a: T, b: T) -> std::cmp::Ordering where T: Iterator, T: Ord { + | +++++++++++++++++++++++++ + +error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:8:7 + | +LL | a.cmp(&b) + | ^^^ method cannot be called on `&T` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `T: Ord` + which is required by `&T: Ord` + `&T: Iterator` + which is required by `&mut &T: Iterator` + `T: Iterator` + which is required by `&mut T: Iterator` +help: consider restricting the type parameters to satisfy the trait bounds + | +LL | fn h(a: &T, b: T) -> std::cmp::Ordering where T: Iterator, T: Ord { + | +++++++++++++++++++++++++ + +error[E0599]: the method `cmp` exists for struct `Box`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:14:7 + | +LL | trait T {} + | ------- + | | + | doesn't satisfy `dyn T: Iterator` + | doesn't satisfy `dyn T: Ord` +... +LL | x.cmp(&x); + | ^^^ method cannot be called on `Box` due to unsatisfied trait bounds + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL + | + = note: doesn't satisfy `Box: Iterator` + | + = note: doesn't satisfy `Box: Ord` + | + = note: the following trait bounds were not satisfied: + `dyn T: Iterator` + which is required by `Box: Iterator` + `dyn T: Ord` + which is required by `Box: Ord` + `Box: Iterator` + which is required by `&mut Box: Iterator` + `dyn T: Iterator` + which is required by `&mut dyn T: Iterator` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. From 20b1c2aafca8d8861d193d3476ffc8d09c0479e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 26 Jan 2024 19:02:05 +0000 Subject: [PATCH 418/676] Account for unbounded type param receiver in suggestions When encountering ```rust fn f(a: T, b: T) -> std::cmp::Ordering { a.cmp(&b) //~ ERROR E0599 } ``` output ``` error[E0599]: no method named `cmp` found for type parameter `T` in the current scope --> $DIR/method-on-unbounded-type-param.rs:2:7 | LL | fn f(a: T, b: T) -> std::cmp::Ordering { | - method `cmp` not found for this type parameter LL | a.cmp(&b) | ^^^ method cannot be called on `T` due to unsatisfied trait bounds | = help: items from traits can only be used if the type parameter is bounded by the trait help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: | LL | fn f(a: T, b: T) -> std::cmp::Ordering { | +++++ LL | fn f(a: T, b: T) -> std::cmp::Ordering { | ++++++++++ ``` Fix #120186. --- .../rustc_hir_typeck/src/method/suggest.rs | 41 ++++++++++++------- .../method-on-unbounded-type-param.stderr | 16 ++++---- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 6c9501e93fa11..de42f011cf42a 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -554,6 +554,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement" )); } + } else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) { + // We special case the situation where we are looking for `_` in + // `::method` because otherwise the machinery will look for blanket + // implementations that have unsatisfied trait bounds to suggest, leading us to claim + // things like "we're looking for a trait with method `cmp`, both `Iterator` and `Ord` + // have one, in order to implement `Ord` you need to restrict `TypeParam: FnPtr` so + // that `impl Ord for T` can apply", which is not what we want. We have a type + // parameter, we want to directly say "`Ord::cmp` and `Iterator::cmp` exist, restrict + // `TypeParam: Ord` or `TypeParam: Iterator`"". That is done further down when calling + // `self.suggest_traits_to_import`, so we ignore the `unsatisfied_predicates` + // suggestions. } else if !unsatisfied_predicates.is_empty() { let mut type_params = FxIndexMap::default(); @@ -1325,7 +1336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); - return Some(err); + Some(err) } fn note_candidates_on_method_error( @@ -2918,19 +2929,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this isn't perfect (that is, there are cases when // implementing a trait would be legal but is rejected // here). - unsatisfied_predicates.iter().all(|(p, _, _)| { - match p.kind().skip_binder() { - // Hide traits if they are present in predicates as they can be fixed without - // having to implement them. - ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => { - t.def_id() == info.def_id - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => { - p.projection_ty.def_id == info.def_id - } - _ => false, - } - }) && (type_is_local || info.def_id.is_local()) + (type_is_local || info.def_id.is_local()) && !self.tcx.trait_is_auto(info.def_id) && self .associated_value(info.def_id, item_name) @@ -2978,6 +2977,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item.visibility(self.tcx).is_public() || info.def_id.is_local() }) .is_some() + && (matches!(rcvr_ty.kind(), ty::Param(_)) + || unsatisfied_predicates.iter().all(|(p, _, _)| { + match p.kind().skip_binder() { + // Hide traits if they are present in predicates as they can be fixed without + // having to implement them. + ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => { + t.def_id() == info.def_id + } + ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => { + p.projection_ty.def_id == info.def_id + } + _ => false, + } + })) }) .collect::>(); for span in &arbitrary_rcvr { diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr index 0b650995de5c5..f12b4d6cabdaf 100644 --- a/tests/ui/traits/method-on-unbounded-type-param.stderr +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -1,18 +1,18 @@ -error[E0599]: `T` is not an iterator +error[E0599]: no method named `cmp` found for type parameter `T` in the current scope --> $DIR/method-on-unbounded-type-param.rs:2:7 | LL | fn f(a: T, b: T) -> std::cmp::Ordering { | - method `cmp` not found for this type parameter LL | a.cmp(&b) - | ^^^ `T` is not an iterator + | ^^^ method cannot be called on `T` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `T: Iterator` - which is required by `&mut T: Iterator` -help: consider restricting the type parameter to satisfy the trait bound + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: | -LL | fn f(a: T, b: T) -> std::cmp::Ordering where T: Iterator { - | +++++++++++++++++ +LL | fn f(a: T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn f(a: T, b: T) -> std::cmp::Ordering { + | ++++++++++ error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied --> $DIR/method-on-unbounded-type-param.rs:5:10 From 9ccc77036a144cc0d172c28e48c330d544ae5471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 30 Jan 2024 19:13:11 +0000 Subject: [PATCH 419/676] fix rebase --- .../method-on-unbounded-type-param.stderr | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr index f12b4d6cabdaf..245c25bbc6f67 100644 --- a/tests/ui/traits/method-on-unbounded-type-param.stderr +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -53,20 +53,11 @@ LL | fn h(a: &T, b: T) -> std::cmp::Ordering where T: Iterator, T: Ord { error[E0599]: the method `cmp` exists for struct `Box`, but its trait bounds were not satisfied --> $DIR/method-on-unbounded-type-param.rs:14:7 | -LL | trait T {} - | ------- - | | - | doesn't satisfy `dyn T: Iterator` - | doesn't satisfy `dyn T: Ord` +LL | trait T {} + | ------- doesn't satisfy `dyn T: Iterator` or `dyn T: Ord` ... -LL | x.cmp(&x); - | ^^^ method cannot be called on `Box` due to unsatisfied trait bounds - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL - ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL - | - = note: doesn't satisfy `Box: Iterator` - | - = note: doesn't satisfy `Box: Ord` +LL | x.cmp(&x); + | ^^^ method cannot be called on `Box` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `dyn T: Iterator` From 5c414094ac8d41038819dd982403f4e3de05d93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 30 Jan 2024 18:10:12 +0000 Subject: [PATCH 420/676] Account for non-overlapping unmet trait bounds in suggestion When a method not found on a type parameter could have been provided by any of multiple traits, suggest each trait individually, instead of a single suggestion to restrict the type parameter with *all* of them. Before: ``` error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied --> $DIR/method-on-unbounded-type-param.rs:5:10 | LL | (&a).cmp(&b) | ^^^ method cannot be called on `&T` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `T: Ord` which is required by `&T: Ord` `&T: Iterator` which is required by `&mut &T: Iterator` `T: Iterator` which is required by `&mut T: Iterator` help: consider restricting the type parameters to satisfy the trait bounds | LL | fn g(a: T, b: T) -> std::cmp::Ordering where T: Iterator, T: Ord { | +++++++++++++++++++++++++ ``` After: ``` error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied --> $DIR/method-on-unbounded-type-param.rs:5:10 | LL | (&a).cmp(&b) | ^^^ method cannot be called on `&T` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `T: Ord` which is required by `&T: Ord` `&T: Iterator` which is required by `&mut &T: Iterator` `T: Iterator` which is required by `&mut T: Iterator` = help: items from traits can only be used if the type parameter is bounded by the trait help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: | LL | fn g(a: T, b: T) -> std::cmp::Ordering { | +++++ LL | fn g(a: T, b: T) -> std::cmp::Ordering { | ++++++++++ ``` Fix #108428. --- .../rustc_hir_typeck/src/method/suggest.rs | 58 +++++++------------ .../box/unit/unique-object-noncopyable.stderr | 3 + tests/ui/box/unit/unique-pinned-nocopy.stderr | 3 - .../derives/derive-assoc-type-not-impl.stderr | 3 - ...method-unsatisfied-assoc-type-predicate.rs | 2 +- ...od-unsatisfied-assoc-type-predicate.stderr | 6 ++ .../trait-bounds/issue-30786.stderr | 12 ++++ tests/ui/methods/method-call-err-msg.stderr | 5 +- .../method-on-unbounded-type-param.stderr | 22 +++++-- 9 files changed, 62 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index de42f011cf42a..f7aa5209e94a7 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -540,6 +540,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut bound_spans: SortedMap> = Default::default(); let mut restrict_type_params = false; + let mut suggested_derive = false; let mut unsatisfied_bounds = false; if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { let msg = "consider using `len` instead"; @@ -927,20 +928,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .enumerate() .collect::>(); - for ((span, add_where_or_comma), obligations) in type_params.into_iter() { - restrict_type_params = true; - // #74886: Sort here so that the output is always the same. - let obligations = obligations.into_sorted_stable_ord(); - err.span_suggestion_verbose( - span, - format!( - "consider restricting the type parameter{s} to satisfy the \ - trait bound{s}", - s = pluralize!(obligations.len()) - ), - format!("{} {}", add_where_or_comma, obligations.join(", ")), - Applicability::MaybeIncorrect, - ); + if !matches!(rcvr_ty.peel_refs().kind(), ty::Param(_)) { + for ((span, add_where_or_comma), obligations) in type_params.into_iter() { + restrict_type_params = true; + // #74886: Sort here so that the output is always the same. + let obligations = obligations.into_sorted_stable_ord(); + err.span_suggestion_verbose( + span, + format!( + "consider restricting the type parameter{s} to satisfy the trait \ + bound{s}", + s = pluralize!(obligations.len()) + ), + format!("{} {}", add_where_or_comma, obligations.join(", ")), + Applicability::MaybeIncorrect, + ); + } } bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically. @@ -988,7 +991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the following trait bounds were not satisfied:\n{bound_list}" )); } - self.suggest_derive(&mut err, unsatisfied_predicates); + suggested_derive = self.suggest_derive(&mut err, unsatisfied_predicates); unsatisfied_bounds = true; } @@ -1211,7 +1214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params { + if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive { } else { self.suggest_traits_to_import( &mut err, @@ -1221,7 +1224,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args.map(|args| args.len() + 1), source, no_match_data.out_of_scope_traits.clone(), - unsatisfied_predicates, static_candidates, unsatisfied_bounds, expected.only_has_type(self), @@ -2481,7 +2483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Option>, Option>, )], - ) { + ) -> bool { let mut derives = self.note_predicate_source_and_get_derives(err, unsatisfied_predicates); derives.sort(); derives.dedup(); @@ -2506,6 +2508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } + !derives_grouped.is_empty() } fn note_derefed_ty_has_method( @@ -2708,11 +2711,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inputs_len: Option, source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec, - unsatisfied_predicates: &[( - ty::Predicate<'tcx>, - Option>, - Option>, - )], static_candidates: &[CandidateSource], unsatisfied_bounds: bool, return_type: Option>, @@ -2977,20 +2975,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item.visibility(self.tcx).is_public() || info.def_id.is_local() }) .is_some() - && (matches!(rcvr_ty.kind(), ty::Param(_)) - || unsatisfied_predicates.iter().all(|(p, _, _)| { - match p.kind().skip_binder() { - // Hide traits if they are present in predicates as they can be fixed without - // having to implement them. - ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => { - t.def_id() == info.def_id - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => { - p.projection_ty.def_id == info.def_id - } - _ => false, - } - })) }) .collect::>(); for span in &arbitrary_rcvr { diff --git a/tests/ui/box/unit/unique-object-noncopyable.stderr b/tests/ui/box/unit/unique-object-noncopyable.stderr index 49547872d1a7b..8ea6edb48a7fc 100644 --- a/tests/ui/box/unit/unique-object-noncopyable.stderr +++ b/tests/ui/box/unit/unique-object-noncopyable.stderr @@ -12,6 +12,9 @@ LL | let _z = y.clone(); which is required by `Box: Clone` `dyn Foo: Clone` which is required by `Box: Clone` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` error: aborting due to 1 previous error diff --git a/tests/ui/box/unit/unique-pinned-nocopy.stderr b/tests/ui/box/unit/unique-pinned-nocopy.stderr index d2bf72249c451..69428604b197f 100644 --- a/tests/ui/box/unit/unique-pinned-nocopy.stderr +++ b/tests/ui/box/unit/unique-pinned-nocopy.stderr @@ -10,9 +10,6 @@ LL | let _j = i.clone(); = note: the following trait bounds were not satisfied: `R: Clone` which is required by `Box: Clone` - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `Clone` help: consider annotating `R` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 61268ffc7f852..13ba80243a5eb 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -15,9 +15,6 @@ note: trait bound `NotClone: Clone` was not satisfied | LL | #[derive(Clone)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `Clone` help: consider annotating `NotClone` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs index add4d58f86a0d..92ce4a0970f36 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs @@ -5,7 +5,7 @@ trait X { type Y; } -trait M { +trait M { //~ NOTE fn f(&self) {} } diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr index 1dd463f996ce6..61512dd46582d 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr @@ -14,6 +14,12 @@ LL | impl = i32>> M for T {} | ^^^^^^^^^^^^ - - | | | unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `M` defines an item `f`, perhaps you need to implement it + --> $DIR/method-unsatisfied-assoc-type-predicate.rs:8:1 + | +LL | trait M { + | ^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr index 73870703cfbac..699a4ecc42bb9 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr @@ -15,6 +15,12 @@ note: the following trait bounds were not satisfied: | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `StreamExt` defines an item `filterx`, perhaps you need to implement it + --> $DIR/issue-30786.rs:66:1 + | +LL | pub trait StreamExt + | ^^^^^^^^^^^^^^^^^^^ error[E0599]: the method `countx` exists for struct `Filter &u64 {identity::}>, {closure@issue-30786.rs:131:30}>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:132:24 @@ -33,6 +39,12 @@ note: the following trait bounds were not satisfied: | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `StreamExt` defines an item `countx`, perhaps you need to implement it + --> $DIR/issue-30786.rs:66:1 + | +LL | pub trait StreamExt + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr index f431085745405..6df49e432a13a 100644 --- a/tests/ui/methods/method-call-err-msg.stderr +++ b/tests/ui/methods/method-call-err-msg.stderr @@ -63,8 +63,9 @@ LL | | .take() note: the trait `Iterator` must be implemented --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `take`, perhaps you need to implement it: - candidate #1: `Iterator` + = note: the following traits define an item `take`, perhaps you need to implement one of them: + candidate #1: `std::io::Read` + candidate #2: `Iterator` error[E0061]: this method takes 3 arguments but 0 arguments were supplied --> $DIR/method-call-err-msg.rs:21:7 diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr index 245c25bbc6f67..0d8bd8ee964e7 100644 --- a/tests/ui/traits/method-on-unbounded-type-param.stderr +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -27,10 +27,13 @@ LL | (&a).cmp(&b) which is required by `&mut &T: Iterator` `T: Iterator` which is required by `&mut T: Iterator` -help: consider restricting the type parameters to satisfy the trait bounds + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: | -LL | fn g(a: T, b: T) -> std::cmp::Ordering where T: Iterator, T: Ord { - | +++++++++++++++++++++++++ +LL | fn g(a: T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn g(a: T, b: T) -> std::cmp::Ordering { + | ++++++++++ error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied --> $DIR/method-on-unbounded-type-param.rs:8:7 @@ -45,10 +48,13 @@ LL | a.cmp(&b) which is required by `&mut &T: Iterator` `T: Iterator` which is required by `&mut T: Iterator` -help: consider restricting the type parameters to satisfy the trait bounds + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: | -LL | fn h(a: &T, b: T) -> std::cmp::Ordering where T: Iterator, T: Ord { - | +++++++++++++++++++++++++ +LL | fn h(a: &T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn h(a: &T, b: T) -> std::cmp::Ordering { + | ++++++++++ error[E0599]: the method `cmp` exists for struct `Box`, but its trait bounds were not satisfied --> $DIR/method-on-unbounded-type-param.rs:14:7 @@ -68,6 +74,10 @@ LL | x.cmp(&x); which is required by `&mut Box: Iterator` `dyn T: Iterator` which is required by `&mut dyn T: Iterator` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `cmp`, perhaps you need to implement one of them: + candidate #1: `Ord` + candidate #2: `Iterator` error: aborting due to 4 previous errors From a97ff2a750edf9ba4a9cdfd72f419f6836fe6b2d Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Tue, 30 Jan 2024 14:37:59 -0500 Subject: [PATCH 421/676] 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 422/676] 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 423/676] 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

` (where P is one of the previous types except `Self`) + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0038, E0307, E0378, E0412, E0658. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs index af471b5e19345..d7a2c8e7a928e 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs @@ -8,6 +8,7 @@ trait Overflow { } impl Overflow for T { type Assoc = ::Assoc; + //~^ ERROR: overflow } diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index e3c0dabf549e8..583945723d5f0 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `::Assoc` - --> $DIR/trait_ref_is_knowable-norm-overflow.rs:17:1 + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1 | LL | impl Trait for T {} | ------------------------- first implementation here @@ -7,6 +7,24 @@ LL | struct LocalTy; LL | impl Trait for ::Assoc {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `::Assoc` -error: aborting due to 1 previous error +error[E0275]: overflow evaluating the requirement `::Assoc: Sized` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18 + | +LL | type Assoc = ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) +note: required by a bound in `Overflow::Assoc` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:7:5 + | +LL | type Assoc; + | ^^^^^^^^^^^ required by this bound in `Overflow::Assoc` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assoc: ?Sized; + | ++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0275. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index 10fb7d525b7a1..c50276c78b4f8 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -12,6 +12,7 @@ trait ToUnit<'a> { trait Overlap {} type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; +//~^ ERROR: not well-formed impl Overlap for T {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index c16a48d5f154c..f4638348358fc 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Missing` in this scope - --> $DIR/issue-118950-root-region.rs:18:55 + --> $DIR/issue-118950-root-region.rs:19:55 | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} | ^^^^^^^ not found in this scope @@ -22,7 +22,7 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) error[E0119]: conflicting implementations of trait `Overlap` for type `fn(_)` - --> $DIR/issue-118950-root-region.rs:18:1 + --> $DIR/issue-118950-root-region.rs:19:1 | LL | impl Overlap for T {} | ------------------------ first implementation here @@ -30,7 +30,13 @@ LL | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` -error: aborting due to 2 previous errors; 1 warning emitted +error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed + --> $DIR/issue-118950-root-region.rs:14:21 + | +LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted Some errors have detailed explanations: E0119, E0412. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index 4eba14f5a93fb..591a7278ddcf6 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -198,6 +198,7 @@ trait Qux { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types } impl Qux for Struct { + //~^ ERROR not all trait items implemented, missing: `F` type A = _; //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types type B = _; diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index a4325b01f02c4..bfcc76c1dae7d 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -29,7 +29,7 @@ LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:205:5 + --> $DIR/typeck_type_placeholder_item.rs:206:5 | LL | const C: _; | ^^^^^^^^^^- @@ -411,7 +411,7 @@ LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/typeck_type_placeholder_item.rs:216:31 + --> $DIR/typeck_type_placeholder_item.rs:217:31 | LL | fn value() -> Option<&'static _> { | ----------------^- @@ -420,7 +420,7 @@ LL | fn value() -> Option<&'static _> { | help: replace with the correct return type: `Option<&'static u8>` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/typeck_type_placeholder_item.rs:221:10 + --> $DIR/typeck_type_placeholder_item.rs:222:10 | LL | const _: Option<_> = map(value); | ^^^^^^^^^ @@ -429,7 +429,7 @@ LL | const _: Option<_> = map(value); | help: replace with the correct type: `Option` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/typeck_type_placeholder_item.rs:224:31 + --> $DIR/typeck_type_placeholder_item.rs:225:31 | LL | fn evens_squared(n: usize) -> _ { | ^ @@ -438,13 +438,13 @@ LL | fn evens_squared(n: usize) -> _ { | help: replace with an appropriate return type: `impl Iterator` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/typeck_type_placeholder_item.rs:229:10 + --> $DIR/typeck_type_placeholder_item.rs:230:10 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^ not allowed in type signatures | -note: however, the inferred type `Map, {closure@typeck_type_placeholder_item.rs:229:29}>, {closure@typeck_type_placeholder_item.rs:229:49}>` cannot be named - --> $DIR/typeck_type_placeholder_item.rs:229:14 +note: however, the inferred type `Map, {closure@typeck_type_placeholder_item.rs:230:29}>, {closure@typeck_type_placeholder_item.rs:230:49}>` cannot be named + --> $DIR/typeck_type_placeholder_item.rs:230:14 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -631,25 +631,25 @@ LL | fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; } | ~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types - --> $DIR/typeck_type_placeholder_item.rs:201:14 + --> $DIR/typeck_type_placeholder_item.rs:202:14 | LL | type A = _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types - --> $DIR/typeck_type_placeholder_item.rs:203:14 + --> $DIR/typeck_type_placeholder_item.rs:204:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:205:14 + --> $DIR/typeck_type_placeholder_item.rs:206:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:208:14 + --> $DIR/typeck_type_placeholder_item.rs:209:14 | LL | const D: _ = 42; | ^ @@ -657,7 +657,16 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error: aborting due to 71 previous errors +error[E0046]: not all trait items implemented, missing: `F` + --> $DIR/typeck_type_placeholder_item.rs:200:1 + | +LL | type F: std::ops::Fn(_); + | ----------------------- `F` from trait +... +LL | impl Qux for Struct { + | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation + +error: aborting due to 72 previous errors -Some errors have detailed explanations: E0121, E0282, E0403. -For more information about an error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0046, E0121, E0282, E0403. +For more information about an error, try `rustc --explain E0046`. From a59a1e7c2c7b4098ecc73fe532ad0cdd14b7075d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sun, 4 Feb 2024 13:07:16 +0000 Subject: [PATCH 564/676] Remove some invalid cfg(doc) code --- library/core/src/primitive_docs.rs | 36 ------------------------------ 1 file changed, 36 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bf47d767a9277..85595b059ad9a 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -448,22 +448,6 @@ mod prim_unit {} #[doc(hidden)] impl () {} -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for () { - fn clone(&self) -> Self { - loop {} - } -} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Copy for () { - // empty -} - #[rustc_doc_primitive = "pointer"] #[doc(alias = "ptr")] #[doc(alias = "*")] @@ -1690,23 +1674,3 @@ mod prim_fn {} // See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] impl fn(T) -> Ret {} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(fake_variadic)] -/// This trait is implemented on function pointers with any number of arguments. -impl Clone for fn(T) -> Ret { - fn clone(&self) -> Self { - loop {} - } -} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(fake_variadic)] -/// This trait is implemented on function pointers with any number of arguments. -impl Copy for fn(T) -> Ret { - // empty -} From d9508a1fd2bdbc2f7c4e2ee28503f15487fdc8ce Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Feb 2024 15:44:22 +1100 Subject: [PATCH 565/676] Make `Emitter::emit_diagnostic` consuming. All the other `emit`/`emit_diagnostic` methods were recently made consuming (e.g. #119606), but this one wasn't. But it makes sense to. Much of this is straightforward, and lots of `clone` calls are avoided. There are a couple of tricky bits. - `Emitter::primary_span_formatted` no longer takes a `Diagnostic` and returns a pair. Instead it takes the two fields from `Diagnostic` that it used (`span` and `suggestions`) as `&mut`, and modifies them. This is necessary to avoid the cloning of `diag.children` in two emitters. - `from_errors_diagnostic` is rearranged so various uses of `diag` occur before the consuming `emit_diagnostic` call. --- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- .../src/annotate_snippet_emitter_writer.rs | 16 +++--- compiler/rustc_errors/src/emitter.rs | 41 +++++++-------- compiler/rustc_errors/src/json.rs | 52 ++++++++++--------- compiler/rustc_errors/src/lib.rs | 26 ++++++---- .../passes/lint/check_code_block_syntax.rs | 2 +- src/tools/rustfmt/src/parse/session.rs | 20 +++---- 7 files changed, 84 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 4211f875dd01a..9b24339d2551f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1810,7 +1810,7 @@ impl Translate for SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { + fn emit_diagnostic(&mut self, diag: rustc_errors::Diagnostic) { let args: FxHashMap = diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect(); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 949f52ef6b586..1ce75a0381237 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -44,15 +44,15 @@ impl Translate for AnnotateSnippetEmitter { impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, mut diag: Diagnostic) { let fluent_args = to_fluent_args(diag.args()); - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args); + let mut suggestions = diag.suggestions.unwrap_or(vec![]); + self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &mut primary_span, - &mut children, + &mut diag.span, + &mut diag.children, &diag.level, self.macro_backtrace, ); @@ -62,9 +62,9 @@ impl Emitter for AnnotateSnippetEmitter { &diag.messages, &fluent_args, &diag.code, - &primary_span, - &children, - suggestions, + &diag.span, + &diag.children, + &suggestions, ); } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 4be5ed923e5e0..12d947f2098b1 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -193,7 +193,7 @@ pub type DynEmitter = dyn Emitter + DynSend; /// Emitter trait for emitting errors. pub trait Emitter: Translate { /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, diag: &Diagnostic); + fn emit_diagnostic(&mut self, diag: Diagnostic); /// Emit a notification that an artifact has been output. /// Currently only supported for the JSON format. @@ -230,17 +230,17 @@ pub trait Emitter: Translate { /// /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, /// we format the `help` suggestion depending on the content of the - /// substitutions. In that case, we return the modified span only. + /// substitutions. In that case, we modify the span and clear the + /// suggestions. /// /// * If the current `Diagnostic` has multiple suggestions, - /// we return the original `primary_span` and the original suggestions. - fn primary_span_formatted<'a>( + /// we leave `primary_span` and the suggestions untouched. + fn primary_span_formatted( &mut self, - diag: &'a Diagnostic, + primary_span: &mut MultiSpan, + suggestions: &mut Vec, fluent_args: &FluentArgs<'_>, - ) -> (MultiSpan, &'a [CodeSuggestion]) { - let mut primary_span = diag.span.clone(); - let suggestions = diag.suggestions.as_deref().unwrap_or(&[]); + ) { if let Some((sugg, rest)) = suggestions.split_first() { let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap(); if rest.is_empty() && @@ -287,16 +287,15 @@ pub trait Emitter: Translate { primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); // We return only the modified primary_span - (primary_span, &[]) + suggestions.clear(); } else { // if there are multiple suggestions, print them all in full // to be consistent. We could try to figure out if we can // make one (or the first one) inline, but that would give // undue importance to a semi-random suggestion - (primary_span, suggestions) } } else { - (primary_span, suggestions) + // do nothing } } @@ -518,16 +517,15 @@ impl Emitter for HumanEmitter { self.sm.as_ref() } - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, mut diag: Diagnostic) { let fluent_args = to_fluent_args(diag.args()); - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args); - debug!("emit_diagnostic: suggestions={:?}", suggestions); + let mut suggestions = diag.suggestions.unwrap_or(vec![]); + self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &mut primary_span, - &mut children, + &mut diag.span, + &mut diag.children, &diag.level, self.macro_backtrace, ); @@ -537,9 +535,9 @@ impl Emitter for HumanEmitter { &diag.messages, &fluent_args, &diag.code, - &primary_span, - &children, - suggestions, + &diag.span, + &diag.children, + &suggestions, self.track_diagnostics.then_some(&diag.emitted_at), ); } @@ -576,9 +574,8 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, mut 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_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 6f92299827950..470e3d52452cf 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -176,7 +176,7 @@ impl Translate for JsonEmitter { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) { + fn emit_diagnostic(&mut self, diag: crate::Diagnostic) { let data = Diagnostic::from_errors_diagnostic(diag, self); let result = self.emit(EmitTyped::Diagnostic(data)); if let Err(e) = result { @@ -201,7 +201,7 @@ impl Emitter for JsonEmitter { } FutureBreakageItem { diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( - &diag, self, + diag, self, )), } }) @@ -340,7 +340,7 @@ struct UnusedExterns<'a, 'b, 'c> { } impl Diagnostic { - fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { + fn from_errors_diagnostic(diag: crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { let args = to_fluent_args(diag.args()); let sugg = diag.suggestions.iter().flatten().map(|sugg| { let translated_message = @@ -382,6 +382,28 @@ impl Diagnostic { Ok(()) } } + + let translated_message = je.translate_messages(&diag.messages, &args); + + let code = if let Some(code) = diag.code { + Some(DiagnosticCode { + code: code.to_string(), + explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(), + }) + } else if let Some(IsLint { name, .. }) = &diag.is_lint { + Some(DiagnosticCode { code: name.to_string(), explanation: None }) + } else { + None + }; + let level = diag.level.to_str(); + let spans = DiagnosticSpan::from_multispan(&diag.span, &args, je); + let children = diag + .children + .iter() + .map(|c| Diagnostic::from_sub_diagnostic(c, &args, je)) + .chain(sugg) + .collect(); + let buf = BufWriter::default(); let output = buf.clone(); je.json_rendered @@ -398,30 +420,12 @@ impl Diagnostic { let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); - let translated_message = je.translate_messages(&diag.messages, &args); - - let code = if let Some(code) = diag.code { - Some(DiagnosticCode { - code: code.to_string(), - explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(), - }) - } else if let Some(IsLint { name, .. }) = &diag.is_lint { - Some(DiagnosticCode { code: name.to_string(), explanation: None }) - } else { - None - }; - Diagnostic { message: translated_message.to_string(), code, - level: diag.level.to_str(), - spans: DiagnosticSpan::from_multispan(&diag.span, &args, je), - children: diag - .children - .iter() - .map(|c| Diagnostic::from_sub_diagnostic(c, &args, je)) - .chain(sugg) - .collect(), + level, + spans, + children, rendered: Some(output), } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b2bd4d8eb956e..a48fcf3af9b02 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -990,9 +990,13 @@ impl DiagCtxt { match (errors.len(), warnings.len()) { (0, 0) => return, - (0, _) => inner - .emitter - .emit_diagnostic(&Diagnostic::new(Warning, DiagnosticMessage::Str(warnings))), + (0, _) => { + // Use `inner.emitter` directly, otherwise the warning might not be emitted, e.g. + // with a configuration like `--cap-lints allow --force-warn bare_trait_objects`. + inner + .emitter + .emit_diagnostic(Diagnostic::new(Warning, DiagnosticMessage::Str(warnings))); + } (_, 0) => { inner.emit_diagnostic(Diagnostic::new(Fatal, errors)); } @@ -1056,7 +1060,7 @@ impl DiagCtxt { } pub fn force_print_diagnostic(&self, db: Diagnostic) { - self.inner.borrow_mut().emitter.emit_diagnostic(&db); + self.inner.borrow_mut().emitter.emit_diagnostic(db); } pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option { @@ -1324,11 +1328,15 @@ impl DiagCtxtInner { !self.emitted_diagnostics.insert(diagnostic_hash) }; + let is_error = diagnostic.is_error(); + let is_lint = diagnostic.is_lint.is_some(); + // Only emit the diagnostic if we've been asked to deduplicate or // haven't already emitted an equivalent diagnostic. if !(self.flags.deduplicate_diagnostics && already_emitted) { debug!(?diagnostic); debug!(?self.emitted_diagnostics); + let already_emitted_sub = |sub: &mut SubDiagnostic| { debug!(?sub); if sub.level != OnceNote && sub.level != OnceHelp { @@ -1340,7 +1348,6 @@ impl DiagCtxtInner { debug!(?diagnostic_hash); !self.emitted_diagnostics.insert(diagnostic_hash) }; - diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {}); if already_emitted { diagnostic.note( @@ -1348,16 +1355,17 @@ impl DiagCtxtInner { ); } - self.emitter.emit_diagnostic(&diagnostic); - if diagnostic.is_error() { + if is_error { self.deduplicated_err_count += 1; } else if matches!(diagnostic.level, ForceWarning(_) | Warning) { self.deduplicated_warn_count += 1; } self.has_printed = true; + + self.emitter.emit_diagnostic(diagnostic); } - if diagnostic.is_error() { - if diagnostic.is_lint.is_some() { + if is_error { + if is_lint { self.lint_err_count += 1; } else { self.err_count += 1; diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index e73649c722493..6649894f9c25d 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -156,7 +156,7 @@ impl Translate for BufferEmitter { } impl Emitter for BufferEmitter { - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, diag: Diagnostic) { let mut buffer = self.buffer.borrow_mut(); let fluent_args = to_fluent_args(diag.args()); diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 6dc3eac44d43d..f0af401d3da4b 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -47,7 +47,7 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, _db: &Diagnostic) {} + fn emit_diagnostic(&mut self, _db: Diagnostic) {} } fn silent_emitter() -> Box { @@ -64,7 +64,7 @@ struct SilentOnIgnoredFilesEmitter { } impl SilentOnIgnoredFilesEmitter { - fn handle_non_ignoreable_error(&mut self, db: &Diagnostic) { + fn handle_non_ignoreable_error(&mut self, db: Diagnostic) { self.has_non_ignorable_parser_errors = true; self.can_reset.store(false, Ordering::Release); self.emitter.emit_diagnostic(db); @@ -86,7 +86,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter { None } - fn emit_diagnostic(&mut self, db: &Diagnostic) { + fn emit_diagnostic(&mut self, db: Diagnostic) { if db.level() == DiagnosticLevel::Fatal { return self.handle_non_ignoreable_error(db); } @@ -365,7 +365,7 @@ mod tests { None } - fn emit_diagnostic(&mut self, _db: &Diagnostic) { + fn emit_diagnostic(&mut self, _db: Diagnostic) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } } @@ -424,7 +424,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); - emitter.emit_diagnostic(&fatal_diagnostic); + emitter.emit_diagnostic(fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -449,7 +449,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(&non_fatal_diagnostic); + emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); assert_eq!(can_reset_errors.load(Ordering::Acquire), true); } @@ -473,7 +473,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(&non_fatal_diagnostic); + emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -512,9 +512,9 @@ mod tests { let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); - emitter.emit_diagnostic(&bar_diagnostic); - emitter.emit_diagnostic(&foo_diagnostic); - emitter.emit_diagnostic(&fatal_diagnostic); + emitter.emit_diagnostic(bar_diagnostic); + emitter.emit_diagnostic(foo_diagnostic); + emitter.emit_diagnostic(fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } From f32aa1aef991d70c5d3a72a2d35fe65a99348d48 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 5 Feb 2024 14:16:40 +0300 Subject: [PATCH 566/676] rustc_metadata: fix typo --- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 542caf8622385..85631bd8edbfa 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -386,7 +386,7 @@ impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> { } } -// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would +// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ @@ -398,7 +398,7 @@ macro_rules! record { }}; } -// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would +// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_array($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record_array { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ From 9f58cf43c78e77b59479da2beaea0265f529280e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jan 2024 13:47:29 +0100 Subject: [PATCH 567/676] get rid of nontrivial_structural_match lint and custom_eq const qualif --- .../src/transform/check_consts/check.rs | 29 +---- .../src/transform/check_consts/qualifs.rs | 32 +---- compiler/rustc_lint/src/lib.rs | 5 + compiler/rustc_lint_defs/src/builtin.rs | 43 +------ compiler/rustc_middle/src/mir/query.rs | 3 +- .../src/thir/pattern/const_to_pat.rs | 113 +++++------------- .../rustc_mir_build/src/thir/pattern/mod.rs | 18 +-- ...corner_cases.rs => accept_corner_cases.rs} | 11 +- .../const_in_pattern/custom-eq-branch-pass.rs | 3 +- .../const_in_pattern/custom-eq-branch-warn.rs | 38 ------ .../custom-eq-branch-warn.stderr | 14 --- .../const_in_pattern/issue-73431.stderr | 1 - .../const_in_pattern/warn_corner_cases.stderr | 36 ------ ...2307-match-ref-ref-forbidden-without-eq.rs | 2 +- ...-match-ref-ref-forbidden-without-eq.stderr | 2 +- 15 files changed, 53 insertions(+), 297 deletions(-) rename tests/ui/consts/const_in_pattern/{warn_corner_cases.rs => accept_corner_cases.rs} (76%) delete mode 100644 tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs delete mode 100644 tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr delete mode 100644 tests/ui/consts/const_in_pattern/issue-73431.stderr delete mode 100644 tests/ui/consts/const_in_pattern/warn_corner_cases.stderr diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 89c65d9232586..5ff81615552bf 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -20,7 +20,7 @@ use std::mem; use std::ops::{ControlFlow, Deref}; use super::ops::{self, NonConstOp, Status}; -use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; +use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; use super::resolver::FlowSensitiveAnalysis; use super::{ConstCx, Qualif}; use crate::const_eval::is_unstable_const_fn; @@ -149,37 +149,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let return_loc = ccx.body.terminator_loc(return_block); - let custom_eq = match ccx.const_kind() { - // We don't care whether a `const fn` returns a value that is not structurally - // matchable. Functions calls are opaque and always use type-based qualification, so - // this value should never be used. - hir::ConstContext::ConstFn => true, - - // If we know that all values of the return type are structurally matchable, there's no - // need to run dataflow. - // Opaque types do not participate in const generics or pattern matching, so we can safely count them out. - _ if ccx.body.return_ty().has_opaque_types() - || !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => - { - false - } - - hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => { - let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx) - .into_engine(ccx.tcx, ccx.body) - .iterate_to_fixpoint() - .into_results_cursor(ccx.body); - - cursor.seek_after_primary_effect(return_loc); - cursor.get().contains(RETURN_PLACE) - } - }; - ConstQualifs { needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc), needs_non_const_drop: self.needs_non_const_drop(ccx, RETURN_PLACE, return_loc), has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc), - custom_eq, tainted_by_errors, } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 1efa52df5817b..67fef20807910 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::*; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty}; use rustc_trait_selection::traits::{ - self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, + ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, }; use super::ConstCx; @@ -24,7 +24,6 @@ pub fn in_any_value_of_ty<'tcx>( has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty), needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty), needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty), - custom_eq: CustomEq::in_any_value_of_ty(cx, ty), tainted_by_errors, } } @@ -213,35 +212,6 @@ impl Qualif for NeedsNonConstDrop { } } -/// A constant that cannot be used as part of a pattern in a `match` expression. -pub struct CustomEq; - -impl Qualif for CustomEq { - const ANALYSIS_NAME: &'static str = "flow_custom_eq"; - - fn in_qualifs(qualifs: &ConstQualifs) -> bool { - qualifs.custom_eq - } - - fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - // If *any* component of a composite data type does not implement `Structural{Partial,}Eq`, - // we know that at least some values of that type are not structural-match. I say "some" - // because that component may be part of an enum variant (e.g., - // `Option::::Some`), in which case some values of this type may be - // structural-match (`Option::None`). - traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some() - } - - fn in_adt_inherently<'tcx>( - cx: &ConstCx<'_, 'tcx>, - def: AdtDef<'tcx>, - args: GenericArgsRef<'tcx>, - ) -> bool { - let ty = Ty::new_adt(cx.tcx, def, args); - !ty.is_structural_eq_shallow(cx.tcx) - } -} - // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. /// Returns `true` if this `Rvalue` contains qualif `Q`. diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 0a15671e68692..1c03de410ee7d 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -520,6 +520,11 @@ fn register_builtins(store: &mut LintStore) { "illegal_floating_point_literal_pattern", "no longer a warning, float patterns behave the same as `==`", ); + store.register_removed( + "nontrivial_structural_match", + "no longer needed, see RFC #3535 \ + for more information", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 07c0e75a71c96..e4298a2636f9f 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3,6 +3,9 @@ //! These are the built-in lints that are emitted direct in the main //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. +//! +//! When removing a lint, make sure to also add a call to `register_removed` in +//! compiler/rustc_lint/src/lib.rs. use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason}; use rustc_span::edition::Edition; @@ -66,7 +69,6 @@ declare_lint_pass! { MUST_NOT_SUSPEND, NAMED_ARGUMENTS_USED_POSITIONALLY, NON_EXHAUSTIVE_OMITTED_PATTERNS, - NONTRIVIAL_STRUCTURAL_MATCH, ORDER_DEPENDENT_TRAIT_OBJECTS, OVERLAPPING_RANGE_ENDPOINTS, PATTERNS_IN_FNS_WITHOUT_BODY, @@ -2341,45 +2343,6 @@ declare_lint! { }; } -declare_lint! { - /// The `nontrivial_structural_match` lint detects constants that are used in patterns, - /// whose type is not structural-match and whose initializer body actually uses values - /// that are not structural-match. So `Option` is ok if the constant - /// is just `None`. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![deny(nontrivial_structural_match)] - /// - /// #[derive(Copy, Clone, Debug)] - /// struct NoDerive(u32); - /// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } - /// impl Eq for NoDerive { } - /// fn main() { - /// const INDEX: Option = [None, Some(NoDerive(10))][0]; - /// match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Previous versions of Rust accepted constants in patterns, even if those constants' types - /// did not have `PartialEq` derived. Thus the compiler falls back to runtime execution of - /// `PartialEq`, which can report that two constants are not equal even if they are - /// bit-equivalent. - pub NONTRIVIAL_STRUCTURAL_MATCH, - Warn, - "constant used in pattern of non-structural-match type and the constant's initializer \ - expression contains values of non-structural-match types", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #73448 ", - }; -} - declare_lint! { /// The `const_patterns_without_partial_eq` lint detects constants that are used in patterns, /// whose type does not implement `PartialEq`. diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 98642adc19090..90b6df1dd1f5e 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -189,7 +189,7 @@ pub struct BorrowCheckResult<'tcx> { /// The result of the `mir_const_qualif` query. /// -/// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in +/// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each /// `Qualif`. #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)] @@ -197,7 +197,6 @@ pub struct ConstQualifs { pub has_mut_interior: bool, pub needs_drop: bool, pub needs_non_const_drop: bool, - pub custom_eq: bool, pub tainted_by_errors: Option, } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 9d3a9bf6745e7..18a00724c3d0e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,6 +1,5 @@ use rustc_apfloat::Float; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_index::Idx; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::Obligation; @@ -17,8 +16,8 @@ use std::cell::Cell; use super::PatCtxt; use crate::errors::{ - IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, - NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, + IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, PointerPattern, + TypeNotStructural, UnionPattern, UnsizedPattern, }; impl<'a, 'tcx> PatCtxt<'a, 'tcx> { @@ -33,11 +32,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { cv: mir::Const<'tcx>, id: hir::HirId, span: Span, - check_body_for_struct_match_violation: Option, ) -> Box> { let infcx = self.tcx.infer_ctxt().build(); let mut convert = ConstToPat::new(self, id, span, infcx); - convert.to_pat(cv, check_body_for_struct_match_violation) + convert.to_pat(cv) } } @@ -103,11 +101,7 @@ impl<'tcx> ConstToPat<'tcx> { ty.is_structural_eq_shallow(self.infcx.tcx) } - fn to_pat( - &mut self, - cv: mir::Const<'tcx>, - check_body_for_struct_match_violation: Option, - ) -> Box> { + fn to_pat(&mut self, cv: mir::Const<'tcx>) -> Box> { trace!(self.treat_byte_string_as_slice); // This method is just a wrapper handling a validity check; the heavy lifting is // performed by the recursive `recur` method, which is not meant to be @@ -116,14 +110,6 @@ impl<'tcx> ConstToPat<'tcx> { // once indirect_structural_match is a full fledged error, this // level of indirection can be eliminated - let mir_structural_match_violation = check_body_for_struct_match_violation.map(|def_id| { - // `mir_const_qualif` must be called with the `DefId` of the item where the const is - // defined, not where it is declared. The difference is significant for associated - // constants. - self.tcx().mir_const_qualif(def_id).custom_eq - }); - debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation); - let have_valtree = matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_))); let inlined_const_as_pat = match cv { @@ -137,15 +123,15 @@ impl<'tcx> ConstToPat<'tcx> { | ty::ConstKind::Expr(_) => { span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind()) } - ty::ConstKind::Value(valtree) => self - .recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false)) - .unwrap_or_else(|_: FallbackToOpaqueConst| { + ty::ConstKind::Value(valtree) => { + self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| { Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Constant { value: cv }, }) - }), + }) + } }, mir::Const::Unevaluated(_, _) => { span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}") @@ -160,7 +146,12 @@ impl<'tcx> ConstToPat<'tcx> { if self.saw_const_match_error.get().is_none() { // If we were able to successfully convert the const to some pat (possibly with some // lints, but no errors), double-check that all types in the const implement - // `Structural` and `PartialEq`. + // `PartialEq`. Even if we have a valtree, we may have found something + // in there with non-structural-equality, meaning we match using `PartialEq` + // and we hence have to check that that impl exists. + // This is all messy but not worth cleaning up: at some point we'll emit + // a hard error when we don't have a valtree or when we find something in + // the valtree that is not structural; then this can all be made a lot simpler. let structural = traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty()); @@ -170,19 +161,12 @@ impl<'tcx> ConstToPat<'tcx> { structural ); - // This can occur because const qualification treats all associated constants as - // opaque, whereas `search_for_structural_match_violation` tries to monomorphize them - // before it runs. - // - // FIXME(#73448): Find a way to bring const qualification into parity with - // `search_for_structural_match_violation`. - if structural.is_none() && mir_structural_match_violation.unwrap_or(false) { - warn!("MIR const-checker found novel structural match violation. See #73448."); - return inlined_const_as_pat; - } - if let Some(non_sm_ty) = structural { if !self.type_has_partial_eq_impl(cv.ty()) { + // This is reachable and important even if we have a valtree: there might be + // non-structural things in a valtree, in which case we fall back to `PartialEq` + // comparison, in which case we better make sure the trait is implemented for + // each inner type (and not just for the surrounding type). let e = if let ty::Adt(def, ..) = non_sm_ty.kind() { if def.is_union() { let err = UnionPattern { span: self.span }; @@ -201,35 +185,18 @@ impl<'tcx> ConstToPat<'tcx> { // We errored. Signal that in the pattern, so that follow up errors can be silenced. let kind = PatKind::Error(e); return Box::new(Pat { span: self.span, ty: cv.ty(), kind }); - } else if let ty::Adt(..) = cv.ty().kind() - && matches!(cv, mir::Const::Val(..)) - { - // This branch is only entered when the current `cv` is `mir::Const::Val`. - // This is because `mir::Const::ty` has already been handled by `Self::recur` - // and the invalid types may be ignored. + } else if !have_valtree { + // Not being structural prevented us from constructing a valtree, + // so this is definitely a case we want to reject. let err = TypeNotStructural { span: self.span, non_sm_ty }; let e = self.tcx().dcx().emit_err(err); let kind = PatKind::Error(e); return Box::new(Pat { span: self.span, ty: cv.ty(), kind }); - } else if !self.saw_const_match_lint.get() { - if let Some(mir_structural_match_violation) = mir_structural_match_violation { - match non_sm_ty.kind() { - ty::Adt(..) if mir_structural_match_violation => { - self.tcx().emit_node_span_lint( - lint::builtin::INDIRECT_STRUCTURAL_MATCH, - self.id, - self.span, - IndirectStructuralMatch { non_sm_ty }, - ); - } - _ => { - debug!( - "`search_for_structural_match_violation` found one, but `CustomEq` was \ - not in the qualifs for that `const`" - ); - } - } - } + } else { + // This could be a violation in an inactive enum variant. + // Since we have a valtree, we trust that we have traversed the full valtree and + // complained about structural match violations there, so we don't + // have to check anything any more. } } else if !have_valtree && !self.saw_const_match_lint.get() { // The only way valtree construction can fail without the structural match @@ -299,7 +266,7 @@ impl<'tcx> ConstToPat<'tcx> { let field = FieldIdx::new(idx); // Patterns can only use monomorphic types. let ty = self.tcx().normalize_erasing_regions(self.param_env, ty); - Ok(FieldPat { field, pattern: self.recur(val, ty, false)? }) + Ok(FieldPat { field, pattern: self.recur(val, ty)? }) }) .collect() } @@ -310,7 +277,6 @@ impl<'tcx> ConstToPat<'tcx> { &self, cv: ValTree<'tcx>, ty: Ty<'tcx>, - mir_structural_match_violation: bool, ) -> Result>, FallbackToOpaqueConst> { let id = self.id; let span = self.span; @@ -395,7 +361,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| self.recur(*val, *elem_ty, false)) + .map(|val| self.recur(*val, *elem_ty)) .collect::>()?, slice: None, suffix: Box::new([]), @@ -404,7 +370,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| self.recur(*val, *elem_ty, false)) + .map(|val| self.recur(*val, *elem_ty)) .collect::>()?, slice: None, suffix: Box::new([]), @@ -471,7 +437,7 @@ impl<'tcx> ConstToPat<'tcx> { _ => *pointee_ty, }; // References have the same valtree representation as their pointee. - let subpattern = self.recur(cv, pointee_ty, false)?; + let subpattern = self.recur(cv, pointee_ty)?; self.behind_reference.set(old); PatKind::Deref { subpattern } } @@ -512,25 +478,6 @@ impl<'tcx> ConstToPat<'tcx> { } }; - if self.saw_const_match_error.get().is_none() - && !self.saw_const_match_lint.get() - && mir_structural_match_violation - // FIXME(#73448): Find a way to bring const qualification into parity with - // `search_for_structural_match_violation` and then remove this condition. - - // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we - // could get `Option`, even though `Option` is annotated with derive. - && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, ty) - { - self.saw_const_match_lint.set(true); - tcx.emit_node_span_lint( - lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH, - id, - span, - NontrivialStructuralMatch { non_sm_ty }, - ); - } - Ok(Box::new(Pat { span, ty, kind })) } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 2190ad14b5511..1a5cf13e28978 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -542,7 +542,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { match const_value { Ok(const_) => { - let pattern = self.const_to_pat(const_, id, span, Some(instance.def_id())); + let pattern = self.const_to_pat(const_, id, span); if !is_associated_const { return pattern; @@ -612,7 +612,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; if let Some(lit_input) = lit_input { match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return self.const_to_pat(Const::Ty(c), id, span, None).kind, + Ok(c) => return self.const_to_pat(Const::Ty(c), id, span).kind, // If an error occurred, ignore that it's a literal // and leave reporting the error up to const eval of // the unevaluated constant below. @@ -635,17 +635,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) { - let subpattern = self.const_to_pat( - Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), - id, - span, - None, - ); + let subpattern = + self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span); PatKind::InlineConstant { subpattern, def: def_id } } else { // If that fails, convert it to an opaque constant pattern. match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) { - Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind, + Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span).kind, Err(ErrorHandled::TooGeneric(_)) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. let e = self.tcx.dcx().emit_err(ConstPatternDependsOnGenericParameter { span }); @@ -681,9 +677,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lit_input = LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(constant) => { - self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind - } + Ok(constant) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind, Err(LitToConstError::Reported(e)) => PatKind::Error(e), Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs b/tests/ui/consts/const_in_pattern/accept_corner_cases.rs similarity index 76% rename from tests/ui/consts/const_in_pattern/warn_corner_cases.rs rename to tests/ui/consts/const_in_pattern/accept_corner_cases.rs index 75f1965921c91..d5b3908f35437 100644 --- a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs +++ b/tests/ui/consts/const_in_pattern/accept_corner_cases.rs @@ -2,9 +2,8 @@ // This test is checking our logic for structural match checking by enumerating // the different kinds of const expressions. This test is collecting cases where -// we have accepted the const expression as a pattern in the past but we want -// to begin warning the user that a future version of Rust may start rejecting -// such const expressions. +// we have accepted the const expression as a pattern in the past and wish to +// continue doing so. // The specific corner cases we are exploring here are instances where the // const-evaluator computes a value that *does* meet the conditions for @@ -24,18 +23,12 @@ impl Eq for NoDerive { } fn main() { const INDEX: Option = [None, Some(NoDerive(10))][0]; match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted const fn build() -> Option { None } const CALL: Option = build(); match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted impl NoDerive { const fn none() -> Option { None } } const METHOD_CALL: Option = NoDerive::none(); match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted } diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs index a38731ceb8a86..ac89b7925ffec 100644 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs +++ b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs @@ -12,6 +12,7 @@ impl PartialEq for CustomEq { } #[derive(PartialEq, Eq)] +#[allow(unused)] enum Foo { Bar, Baz, @@ -21,7 +22,7 @@ enum Foo { const BAR_BAZ: Foo = if 42 == 42 { Foo::Bar } else { - Foo::Baz + Foo::Qux(CustomEq) // dead arm }; fn main() { diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs deleted file mode 100644 index 34b1422dfb3cb..0000000000000 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs +++ /dev/null @@ -1,38 +0,0 @@ -// check-pass - -struct CustomEq; - -impl Eq for CustomEq {} -impl PartialEq for CustomEq { - fn eq(&self, _: &Self) -> bool { - false - } -} - -#[derive(PartialEq, Eq)] -enum Foo { - Bar, - Baz, - Qux(CustomEq), -} - -// We know that `BAR_BAZ` will always be `Foo::Bar` and thus eligible for structural matching, but -// dataflow will be more conservative. -const BAR_BAZ: Foo = if 42 == 42 { - Foo::Bar -} else { - Foo::Qux(CustomEq) -}; - -fn main() { - match Foo::Qux(CustomEq) { - BAR_BAZ => panic!(), - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details - //~| WARN this was previously accepted - //~| NOTE see issue #73448 - //~| NOTE `#[warn(nontrivial_structural_match)]` on by default - _ => {} - } -} diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr deleted file mode 100644 index c473c00f8dbbd..0000000000000 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr +++ /dev/null @@ -1,14 +0,0 @@ -warning: to use a constant of type `CustomEq` in a pattern, the constant's initializer must be trivial or `CustomEq` must be annotated with `#[derive(PartialEq)]` - --> $DIR/custom-eq-branch-warn.rs:29:9 - | -LL | BAR_BAZ => panic!(), - | ^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - = note: `#[warn(nontrivial_structural_match)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/consts/const_in_pattern/issue-73431.stderr b/tests/ui/consts/const_in_pattern/issue-73431.stderr deleted file mode 100644 index c82dea4aa50df..0000000000000 --- a/tests/ui/consts/const_in_pattern/issue-73431.stderr +++ /dev/null @@ -1 +0,0 @@ -WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448. diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr b/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr deleted file mode 100644 index 8ffd035ebec61..0000000000000 --- a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr +++ /dev/null @@ -1,36 +0,0 @@ -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:26:47 - | -LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - = note: `#[warn(nontrivial_structural_match)]` on by default - -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:32:47 - | -LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:38:47 - | -LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; - | ^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -warning: 3 warnings emitted - diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs index fdb67bcf2d8e4..374e5d5acd080 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs @@ -10,7 +10,7 @@ // Issue 62307 pointed out a case where the structural-match checking // was too shallow. -#![warn(indirect_structural_match, nontrivial_structural_match)] +#![warn(indirect_structural_match)] // run-pass #[derive(Debug)] diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr index d0f2b820afa90..3e140a9317ef7 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr @@ -11,7 +11,7 @@ LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); note: the lint level is defined here --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 | -LL | #![warn(indirect_structural_match, nontrivial_structural_match)] +LL | #![warn(indirect_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` From 48abca761a3479d0ae5a41a338dcbe742e240d7c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jan 2024 13:52:06 +0100 Subject: [PATCH 568/676] show indirect_structural_match and pointer_structural_match in future compat reports --- compiler/rustc_lint_defs/src/builtin.rs | 4 +- .../match/match-edge-cases_1.stderr | 11 ++ ...ssue-34784-match-on-non-int-raw-ptr.stderr | 60 ++++++++++ .../const_in_pattern/issue-44333.stderr | 30 +++++ .../reject_non_structural.stderr | 17 +++ .../const-partial_eq-fallback-ice.stderr | 18 +++ .../pattern/usefulness/consts-opaque.stderr | 88 ++++++++++++++ ...ide-behind-doubly-indirect-embedded.stderr | 17 +++ ...t-hide-behind-doubly-indirect-param.stderr | 17 +++ ...ide-behind-indirect-struct-embedded.stderr | 17 +++ ...t-hide-behind-indirect-struct-param.stderr | 17 +++ .../fn-ptr-is-structurally-matchable.stderr | 110 ++++++++++++++++++ ...-match-ref-ref-forbidden-without-eq.stderr | 34 ++++++ .../issue-63479-match-fnptr.stderr | 30 +++++ 14 files changed, 468 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e4298a2636f9f..5bd25b4a54b57 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2282,7 +2282,7 @@ declare_lint! { Warn, "constant used in pattern contains value of non-structural-match type in a field or a variant", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #62411 ", }; } @@ -2338,7 +2338,7 @@ declare_lint! { Warn, "pointers are not structural-match", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #62411 ", }; } diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr index c83ba41976bcd..7aa83de84ee71 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr @@ -10,3 +10,14 @@ LL | NUMBER_POINTER => (), warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/match-edge-cases_1.rs:29:13 + | +LL | NUMBER_POINTER => (), + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr index 1546f23908c6f..416343a14dd27 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -41,3 +41,63 @@ LL | STR => {} error: aborting due to 4 previous errors +Future incompatibility report: Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:10:9 + | +LL | C => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:18:9 + | +LL | C_INNER => {} + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9 + | +LL | D => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9 + | +LL | STR => {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index 441aeecbc6d95..8b62e2a505746 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -23,3 +23,33 @@ LL | BAR => println!("bar"), warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:19:9 + | +LL | FOO => println!("foo"), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-44333.rs:3:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:21:9 + | +LL | BAR => println!("bar"), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-44333.rs:3:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index da32b6d698bb5..31202e26044af 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -97,3 +97,20 @@ LL | #![warn(indirect_structural_match)] error: aborting due to 9 previous errors; 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/reject_non_structural.rs:98:29 + | +LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/reject_non_structural.rs:14:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr index 0b4d99727581b..2c38dc516bf84 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -9,3 +9,21 @@ LL | if let CONSTANT = &&MyType { error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq)]` + --> $DIR/const-partial_eq-fallback-ice.rs:14:12 + | +LL | if let CONSTANT = &&MyType { + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/const-partial_eq-fallback-ice.rs:1:10 + | +LL | #![allow(warnings)] + | ^^^^^^^^ + = note: `#[allow(indirect_structural_match)]` implied by `#[allow(warnings)]` + diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 0b1a2e2736e1d..ca87f4a2aeec8 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -166,3 +166,91 @@ LL | WRAPQUUX => {}, Wrap(_) => todo!() error: aborting due to 10 previous errors; 8 warnings emitted For more information about this error, try `rustc --explain E0004`. +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:96:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:98:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:108:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:110:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:117:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:127:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:139:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:142:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr index 910d491baaf43..fc8dd75af6881 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9 + | +LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr index cadd9be023c50..7c4c72bf888c6 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9 + | +LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr index e4321cc6a4c71..e0c75c94da307 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9 + | +LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr index decc29ad67cd2..0f815daf8a2eb 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9 + | +LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr index 080bf5885ba75..cebe4a26d31ea 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr @@ -91,3 +91,113 @@ LL | CFOO => count += 1, warning: 10 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:43:14 + | +LL | Wrap(CFN1) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:52:14 + | +LL | Wrap(CFN2) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 + | +LL | Wrap(CFN3) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 + | +LL | Wrap(CFN4) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 + | +LL | Wrap(CFN5) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 + | +LL | Wrap(CFN6) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 + | +LL | Wrap(CFN7) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 + | +LL | Wrap(CFN8) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 + | +LL | Wrap(CFN9) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 + | +LL | CFOO => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr index 3e140a9317ef7..1665a9c8078ad 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr @@ -27,3 +27,37 @@ LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9 + | +LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9 + | +LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); } + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index 4fdfce60bb861..fa672f7ef22e6 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -23,3 +23,33 @@ LL | TEST2 => println!("matched"), warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:36:7 + | +LL | B(TEST) => println!("matched"), + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-63479-match-fnptr.rs:8:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:42:5 + | +LL | TEST2 => println!("matched"), + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-63479-match-fnptr.rs:8:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + From 45d01b81311b0888530cd9a394b62d6af04bd972 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jan 2024 14:22:56 +0100 Subject: [PATCH 569/676] update the tracking issue for structural match violations and bless a test I missed --- compiler/rustc_lint_defs/src/builtin.rs | 4 +- .../match/match-edge-cases_1.stderr | 4 +- ...ssue-34784-match-on-non-int-raw-ptr.stderr | 16 ++++---- .../const_in_pattern/issue-44333.stderr | 8 ++-- .../const_in_pattern/reject_non_structural.rs | 2 +- .../reject_non_structural.stderr | 4 +- tests/ui/consts/issue-89088.stderr | 17 ++++++++ .../const-partial_eq-fallback-ice.stderr | 2 +- .../pattern/usefulness/consts-opaque.stderr | 32 +++++++-------- ...ide-behind-doubly-indirect-embedded.stderr | 4 +- ...t-hide-behind-doubly-indirect-param.stderr | 4 +- ...ide-behind-indirect-struct-embedded.stderr | 4 +- ...t-hide-behind-indirect-struct-param.stderr | 4 +- .../fn-ptr-is-structurally-matchable.stderr | 40 +++++++++---------- ...-match-ref-ref-forbidden-without-eq.stderr | 8 ++-- .../issue-63479-match-fnptr.stderr | 8 ++-- 16 files changed, 89 insertions(+), 72 deletions(-) create mode 100644 tests/ui/consts/issue-89088.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 5bd25b4a54b57..6a2a2c1e48e2a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2283,7 +2283,7 @@ declare_lint! { "constant used in pattern contains value of non-structural-match type in a field or a variant", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, - reference: "issue #62411 ", + reference: "issue #120362 ", }; } @@ -2339,7 +2339,7 @@ declare_lint! { "pointers are not structural-match", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, - reference: "issue #62411 ", + reference: "issue #120362 ", }; } diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr index 7aa83de84ee71..8a2aaade66503 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr @@ -5,7 +5,7 @@ LL | NUMBER_POINTER => (), | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default warning: 1 warning emitted @@ -18,6 +18,6 @@ LL | NUMBER_POINTER => (), | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr index 416343a14dd27..bc1015c173426 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -5,7 +5,7 @@ LL | C => {} | ^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 | @@ -19,7 +19,7 @@ LL | C_INNER => {} | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9 @@ -28,7 +28,7 @@ LL | D => {} | ^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9 @@ -37,7 +37,7 @@ LL | STR => {} | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 error: aborting due to 4 previous errors @@ -49,7 +49,7 @@ LL | C => {} | ^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 | @@ -64,7 +64,7 @@ LL | C_INNER => {} | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 | @@ -79,7 +79,7 @@ LL | D => {} | ^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 | @@ -94,7 +94,7 @@ LL | STR => {} | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 | diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index 8b62e2a505746..f5931f0cad08b 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -5,7 +5,7 @@ LL | FOO => println!("foo"), | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-44333.rs:3:9 | @@ -19,7 +19,7 @@ LL | BAR => println!("bar"), | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: 2 warnings emitted @@ -31,7 +31,7 @@ LL | FOO => println!("foo"), | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-44333.rs:3:9 | @@ -46,7 +46,7 @@ LL | BAR => println!("bar"), | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-44333.rs:3:9 | diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs index 196930baed5de..71d4138104db1 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -100,5 +100,5 @@ fn main() { //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details //~| WARN previously accepted by the compiler but is being phased out - //~| NOTE for more information, see issue #62411 + //~| NOTE for more information, see } diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index 31202e26044af..2c7aaf89aa787 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -86,7 +86,7 @@ LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops") | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -105,7 +105,7 @@ LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops") | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr new file mode 100644 index 0000000000000..d5c5f76b90a01 --- /dev/null +++ b/tests/ui/consts/issue-89088.stderr @@ -0,0 +1,17 @@ +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `Cow<'_, str>` in a pattern, `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-89088.rs:19:9 + | +LL | FOO => todo!(), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-89088.rs:5:10 + | +LL | #![allow(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr index 2c38dc516bf84..59b454d398195 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -17,7 +17,7 @@ LL | if let CONSTANT = &&MyType { | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index ca87f4a2aeec8..6a5bd185e39b3 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -5,7 +5,7 @@ LL | QUUX => {} | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. @@ -15,7 +15,7 @@ LL | QUUX => {} | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:108:9 @@ -24,7 +24,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:110:9 @@ -33,7 +33,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:117:9 @@ -42,7 +42,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:127:9 @@ -51,7 +51,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:139:9 @@ -60,7 +60,7 @@ LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:142:9 @@ -69,7 +69,7 @@ LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 error: unreachable pattern --> $DIR/consts-opaque.rs:48:9 @@ -174,7 +174,7 @@ LL | QUUX => {} | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -185,7 +185,7 @@ LL | QUUX => {} | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -196,7 +196,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -207,7 +207,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -218,7 +218,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -229,7 +229,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -240,7 +240,7 @@ LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -251,6 +251,6 @@ LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr index fc8dd75af6881..9945041113d79 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr @@ -5,7 +5,7 @@ LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLIN | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -24,7 +24,7 @@ LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLIN | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr index 7c4c72bf888c6..6ac261ae81437 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr @@ -5,7 +5,7 @@ LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -24,7 +24,7 @@ LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr index e0c75c94da307..41616fb90fe96 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr @@ -5,7 +5,7 @@ LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itse | ^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -24,7 +24,7 @@ LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itse | ^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr index 0f815daf8a2eb..99dea5171d1bc 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr @@ -5,7 +5,7 @@ LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself | ^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -24,7 +24,7 @@ LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself | ^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr index cebe4a26d31ea..11163ba70ec65 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr @@ -5,7 +5,7 @@ LL | Wrap(CFN1) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. @@ -15,7 +15,7 @@ LL | Wrap(CFN2) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 @@ -24,7 +24,7 @@ LL | Wrap(CFN3) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 @@ -33,7 +33,7 @@ LL | Wrap(CFN4) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 @@ -42,7 +42,7 @@ LL | Wrap(CFN5) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 @@ -51,7 +51,7 @@ LL | Wrap(CFN6) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 @@ -60,7 +60,7 @@ LL | Wrap(CFN7) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 @@ -69,7 +69,7 @@ LL | Wrap(CFN8) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 @@ -78,7 +78,7 @@ LL | Wrap(CFN9) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 @@ -87,7 +87,7 @@ LL | CFOO => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: 10 warnings emitted @@ -99,7 +99,7 @@ LL | Wrap(CFN1) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -110,7 +110,7 @@ LL | Wrap(CFN2) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -121,7 +121,7 @@ LL | Wrap(CFN3) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -132,7 +132,7 @@ LL | Wrap(CFN4) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -143,7 +143,7 @@ LL | Wrap(CFN5) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -154,7 +154,7 @@ LL | Wrap(CFN6) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -165,7 +165,7 @@ LL | Wrap(CFN7) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -176,7 +176,7 @@ LL | Wrap(CFN8) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -187,7 +187,7 @@ LL | Wrap(CFN9) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default Future breakage diagnostic: @@ -198,6 +198,6 @@ LL | CFOO => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr index 1665a9c8078ad..d4ab1ce3ba2ad 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr @@ -5,7 +5,7 @@ LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -21,7 +21,7 @@ LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details @@ -35,7 +35,7 @@ LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -52,7 +52,7 @@ LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index fa672f7ef22e6..0edcf44c4d795 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -5,7 +5,7 @@ LL | B(TEST) => println!("matched"), | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-63479-match-fnptr.rs:8:9 | @@ -19,7 +19,7 @@ LL | TEST2 => println!("matched"), | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: 2 warnings emitted @@ -31,7 +31,7 @@ LL | B(TEST) => println!("matched"), | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-63479-match-fnptr.rs:8:9 | @@ -46,7 +46,7 @@ LL | TEST2 => println!("matched"), | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-63479-match-fnptr.rs:8:9 | From e00df17abd6eabfead30dce439592b1902fd0acd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 28 Jan 2024 10:03:02 +0100 Subject: [PATCH 570/676] merge the accepted-structural-match tests into one --- .../const_in_pattern/accept_corner_cases.rs | 34 ------------------- .../const_in_pattern/accept_structural.rs | 14 ++++++++ 2 files changed, 14 insertions(+), 34 deletions(-) delete mode 100644 tests/ui/consts/const_in_pattern/accept_corner_cases.rs diff --git a/tests/ui/consts/const_in_pattern/accept_corner_cases.rs b/tests/ui/consts/const_in_pattern/accept_corner_cases.rs deleted file mode 100644 index d5b3908f35437..0000000000000 --- a/tests/ui/consts/const_in_pattern/accept_corner_cases.rs +++ /dev/null @@ -1,34 +0,0 @@ -// run-pass - -// This test is checking our logic for structural match checking by enumerating -// the different kinds of const expressions. This test is collecting cases where -// we have accepted the const expression as a pattern in the past and wish to -// continue doing so. - -// The specific corner cases we are exploring here are instances where the -// const-evaluator computes a value that *does* meet the conditions for -// structural-match, but the const expression itself has abstractions (like -// calls to const functions) that may fit better with a type-based analysis -// rather than a commitment to a specific value. - -#![warn(indirect_structural_match)] - -#[derive(Copy, Clone, Debug)] -struct NoDerive(#[allow(dead_code)] u32); - -// This impl makes `NoDerive` irreflexive. -impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } -impl Eq for NoDerive { } - -fn main() { - const INDEX: Option = [None, Some(NoDerive(10))][0]; - match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - - const fn build() -> Option { None } - const CALL: Option = build(); - match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; - - impl NoDerive { const fn none() -> Option { None } } - const METHOD_CALL: Option = NoDerive::none(); - match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; -} diff --git a/tests/ui/consts/const_in_pattern/accept_structural.rs b/tests/ui/consts/const_in_pattern/accept_structural.rs index 1f56f581c0270..69b4e75c62236 100644 --- a/tests/ui/consts/const_in_pattern/accept_structural.rs +++ b/tests/ui/consts/const_in_pattern/accept_structural.rs @@ -63,4 +63,18 @@ fn main() { const ADDR_OF: &OND = &None; match &None { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; + + // These ones are more subtle: the final value is fine, but statically analyzing the expression + // that computes the value would likely (incorrectly) have us conclude that this may match on + // values that do not have structural equality. + const INDEX: Option = [None, Some(NoDerive(10))][0]; + match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; + + const fn build() -> Option { None } + const CALL: Option = build(); + match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; + + impl NoDerive { const fn none() -> Option { None } } + const METHOD_CALL: Option = NoDerive::none(); + match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; } From 0184ca695bf10416211163008c3432d9d8144852 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 14 Nov 2023 09:31:41 +0100 Subject: [PATCH 571/676] revert stabilization of const_intrinsic_copy --- library/core/src/intrinsics.rs | 8 ++++---- library/core/src/lib.rs | 1 + library/core/src/ptr/const_ptr.rs | 4 ++-- library/core/src/ptr/mod.rs | 7 +++++-- library/core/src/ptr/mut_ptr.rs | 8 ++++---- library/core/tests/lib.rs | 1 + tests/ui/consts/const-eval/raw-pointer-ub.rs | 2 +- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 43124535ab5d8..6ea80c8d42faa 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2749,13 +2749,13 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - #[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[rustc_nounwind] pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } @@ -2845,13 +2845,13 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[rustc_nounwind] fn copy(src: *const T, dst: *mut T, count: usize); } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a3279dcafef48..09d589f7cd807 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -135,6 +135,7 @@ #![feature(const_hint_assert_unchecked)] #![feature(const_index_range_slice_index)] #![feature(const_int_unchecked_arith)] +#![feature(const_intrinsic_copy)] #![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index f3ceadee24c2f..1d5d683fa16cc 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1284,7 +1284,7 @@ impl *const T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1304,7 +1304,7 @@ impl *const T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index dce7e035fc73a..bc05b5b07def3 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1176,7 +1176,6 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] -#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_read"] pub const unsafe fn read(src: *const T) -> T { @@ -1294,7 +1293,11 @@ pub const unsafe fn read(src: *const T) -> T { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] -#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] +#[rustc_allow_const_fn_unstable( + const_mut_refs, + const_maybe_uninit_as_mut_ptr, + const_intrinsic_copy +)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_read_unaligned"] pub const unsafe fn read_unaligned(src: *const T) -> T { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 3e47c4f440a44..376673d67c10b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1385,7 +1385,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1405,7 +1405,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1425,7 +1425,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1445,7 +1445,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 9a3b477c2d159..15298e1c81622 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -14,6 +14,7 @@ #![feature(const_cell_into_inner)] #![feature(const_hash)] #![feature(const_heap)] +#![feature(const_intrinsic_copy)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_nonnull_new)] #![feature(const_pointer_is_aligned)] diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs index 3341f3c78e0d6..47105de453cb1 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.rs +++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs @@ -1,4 +1,4 @@ -#![feature(const_mut_refs)] +#![feature(const_mut_refs, const_intrinsic_copy)] const MISALIGNED_LOAD: () = unsafe { From 16cbdd0321f342093b71026dc1c5126606e4abe9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 18 Jan 2024 16:39:20 +0000 Subject: [PATCH 572/676] Allow desugaring async fn in trait to compatible, concrete future types --- compiler/rustc_hir_analysis/messages.ftl | 4 --- .../src/check/compare_impl_item.rs | 31 ------------------- compiler/rustc_hir_analysis/src/errors.rs | 11 ------- .../in-trait/async-example-desugared-boxed.rs | 2 +- .../async-example-desugared-boxed.stderr | 11 ------- .../async-example-desugared-manual.rs | 2 +- .../async-example-desugared-manual.stderr | 11 ------- .../async-await/in-trait/fn-not-async-err.rs | 2 +- .../in-trait/fn-not-async-err.stderr | 18 +++++++---- 9 files changed, 15 insertions(+), 77 deletions(-) delete mode 100644 tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr delete mode 100644 tests/ui/async-await/in-trait/async-example-desugared-manual.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 54d0fb6ffab72..d0fb0e3fb7646 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -33,10 +33,6 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the as hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes -hir_analysis_async_trait_impl_should_be_async = - method `{$method_name}` should be async because the method from the trait is async - .trait_item_label = required because the trait method is async - hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` .label = deref recursion limit reached .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 379c1154e5f26..f9c1ed0e0e1da 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -74,7 +74,6 @@ fn check_method_is_structurally_compatible<'tcx>( compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?; compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?; compare_synthetic_generics(tcx, impl_m, trait_m, delay)?; - compare_asyncness(tcx, impl_m, trait_m, delay)?; check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?; Ok(()) } @@ -414,36 +413,6 @@ impl<'tcx> TypeFolder> for RemapLateBound<'_, 'tcx> { } } -fn compare_asyncness<'tcx>( - tcx: TyCtxt<'tcx>, - impl_m: ty::AssocItem, - trait_m: ty::AssocItem, - delay: bool, -) -> Result<(), ErrorGuaranteed> { - if tcx.asyncness(trait_m.def_id).is_async() { - match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() { - ty::Alias(ty::Opaque, ..) => { - // allow both `async fn foo()` and `fn foo() -> impl Future` - } - ty::Error(_) => { - // We don't know if it's ok, but at least it's already an error. - } - _ => { - return Err(tcx - .dcx() - .create_err(crate::errors::AsyncTraitImplShouldBeAsync { - span: tcx.def_span(impl_m.def_id), - method_name: trait_m.name, - trait_item_span: tcx.hir().span_if_local(trait_m.def_id), - }) - .emit_unless(delay)); - } - }; - } - - Ok(()) -} - /// Given a method def-id in an impl, compare the method signature of the impl /// against the trait that it's implementing. In doing so, infer the hidden types /// that this method's signature provides to satisfy each return-position `impl Trait` diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 4eba31e327f68..8b8c0f7ff8dbb 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -166,17 +166,6 @@ pub struct LifetimesOrBoundsMismatchOnTrait { pub ident: Ident, } -#[derive(Diagnostic)] -#[diag(hir_analysis_async_trait_impl_should_be_async)] -pub struct AsyncTraitImplShouldBeAsync { - #[primary_span] - // #[label] - pub span: Span, - #[label(hir_analysis_trait_item_label)] - pub trait_item_span: Option, - pub method_name: Symbol, -} - #[derive(Diagnostic)] #[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] pub struct DropImplOnWrongItem { diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs index c5a9841029e38..4008e09998e47 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -1,4 +1,5 @@ // edition: 2021 +// check-pass use std::future::Future; use std::pin::Pin; @@ -9,7 +10,6 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> Pin + '_>> { - //~^ ERROR method `foo` should be async Box::pin(async { *self }) } } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr deleted file mode 100644 index 1462c694e161e..0000000000000 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: method `foo` should be async because the method from the trait is async - --> $DIR/async-example-desugared-boxed.rs:11:5 - | -LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async -... -LL | fn foo(&self) -> Pin + '_>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs index c287b9a5b847f..75f4ba1d076c6 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs @@ -1,4 +1,5 @@ // edition: 2021 +// check-pass use std::future::Future; use std::task::Poll; @@ -17,7 +18,6 @@ impl Future for MyFuture { impl MyTrait for u32 { fn foo(&self) -> MyFuture { - //~^ ERROR method `foo` should be async MyFuture } } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr deleted file mode 100644 index a2f1060e36fc4..0000000000000 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: method `foo` should be async because the method from the trait is async - --> $DIR/async-example-desugared-manual.rs:19:5 - | -LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async -... -LL | fn foo(&self) -> MyFuture { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs index 60077a7e00cc8..6261ed1f1b7b3 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs @@ -8,7 +8,7 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> i32 { - //~^ ERROR: method `foo` should be async + //~^ ERROR: `i32` is not a future *self } } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr index f75ccb65d1509..dc46077d583af 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr @@ -1,11 +1,17 @@ -error: method `foo` should be async because the method from the trait is async - --> $DIR/fn-not-async-err.rs:10:5 +error[E0277]: `i32` is not a future + --> $DIR/fn-not-async-err.rs:10:22 | -LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async -... LL | fn foo(&self) -> i32 { - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^ `i32` is not a future + | + = help: the trait `Future` is not implemented for `i32` + = note: i32 must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `MyTrait::{opaque#0}` + --> $DIR/fn-not-async-err.rs:6:5 + | +LL | async fn foo(&self) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MyTrait::{opaque#0}` error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0277`. From 9aff42e358c8199d5667b92f157f753814c39235 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 5 Feb 2024 14:59:07 -0600 Subject: [PATCH 573/676] Update src/doc/rustc/src/platform-support.md --- src/doc/rustc/src/platform-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 13a7b483d6f3d..80d9dc85f162a 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -278,9 +278,9 @@ target | std | host | notes [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat [`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * | | Bare ARMv7-A, hardfloat -[`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare ARMv8-R, hardfloat [`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARMv7-A Apple WatchOS `armv7s-apple-ios` | ✓ | | ARMv7-A Apple-A6 Apple iOS +[`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare ARMv8-R, hardfloat `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) From e65abc0ea58f2f7dd6812fafa92c4f5b2a28af7b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 18 Jan 2024 17:20:39 +0000 Subject: [PATCH 574/676] Make the error message better --- compiler/rustc_hir_analysis/messages.ftl | 3 + .../src/check/compare_impl_item.rs | 57 +++++++++++++++++-- compiler/rustc_hir_analysis/src/errors.rs | 10 ++++ .../async-await/in-trait/fn-not-async-err.rs | 2 +- .../in-trait/fn-not-async-err.stderr | 13 ++--- 5 files changed, 72 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index d0fb0e3fb7646..d6f604c180bf6 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -206,6 +206,9 @@ hir_analysis_manual_implementation = .label = manual implementations of `{$trait_name}` are experimental .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable +hir_analysis_method_should_return_future = method should be `async` or return a future, but it is synchronous + .note = this method is `async` so it expects a future to be returned + hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}` .label = missing one of `{$missing_items_msg}` in implementation .note = required because of this annotation diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index f9c1ed0e0e1da..18037ea6991e8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1,5 +1,5 @@ use super::potentially_plural_count; -use crate::errors::LifetimesOrBoundsMismatchOnTrait; +use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture}; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; @@ -10,7 +10,7 @@ use rustc_hir::{GenericParamKind, ImplItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::util; +use rustc_infer::traits::{util, FulfillmentError}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; @@ -664,8 +664,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // RPITs. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(errors); - return Err(reported); + if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig) + { + return Err(guar); + } + + let guar = infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(guar); } // Finally, resolve all regions. This catches wily misuses of @@ -2217,3 +2222,47 @@ fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { ty::AssocKind::Type => "type", } } + +/// Manually check here that `async fn foo()` wasn't matched against `fn foo()`, +/// and extract a better error if so. +fn try_report_async_mismatch<'tcx>( + tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'tcx>, + errors: &[FulfillmentError<'tcx>], + trait_m: ty::AssocItem, + impl_m: ty::AssocItem, + impl_sig: ty::FnSig<'tcx>, +) -> Result<(), ErrorGuaranteed> { + if !tcx.asyncness(trait_m.def_id).is_async() { + return Ok(()); + } + + let ty::Alias(ty::Projection, ty::AliasTy { def_id: async_future_def_id, .. }) = + *tcx.fn_sig(trait_m.def_id).skip_binder().skip_binder().output().kind() + else { + bug!("expected `async fn` to return an RPITIT"); + }; + + for error in errors { + if let traits::BindingObligation(def_id, _) = *error.root_obligation.cause.code() + && def_id == async_future_def_id + && let Some(proj) = error.root_obligation.predicate.to_opt_poly_projection_pred() + && let Some(proj) = proj.no_bound_vars() + && infcx.can_eq( + error.root_obligation.param_env, + proj.term.ty().unwrap(), + impl_sig.output(), + ) + { + // FIXME: We should suggest making the fn `async`, but extracting + // the right span is a bit difficult. + return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture { + span: tcx.def_span(impl_m.def_id), + method_name: trait_m.name, + trait_item_span: tcx.hir().span_if_local(trait_m.def_id), + })); + } + } + + Ok(()) +} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 8b8c0f7ff8dbb..bec53693d6c94 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1501,6 +1501,16 @@ pub struct NotSupportedDelegation<'a> { pub callee_span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_method_should_return_future)] +pub struct MethodShouldReturnFuture { + #[primary_span] + pub span: Span, + pub method_name: Symbol, + #[note] + pub trait_item_span: Option, +} + #[derive(Diagnostic)] #[diag(hir_analysis_unused_generic_parameter)] pub(crate) struct UnusedGenericParameter { diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs index 6261ed1f1b7b3..ecd5737cf3c23 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs @@ -8,7 +8,7 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> i32 { - //~^ ERROR: `i32` is not a future + //~^ ERROR: method should be `async` or return a future, but it is synchronous *self } } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr index dc46077d583af..8260cd5271ee9 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr @@ -1,17 +1,14 @@ -error[E0277]: `i32` is not a future - --> $DIR/fn-not-async-err.rs:10:22 +error: method should be `async` or return a future, but it is synchronous + --> $DIR/fn-not-async-err.rs:10:5 | LL | fn foo(&self) -> i32 { - | ^^^ `i32` is not a future + | ^^^^^^^^^^^^^^^^^^^^ | - = help: the trait `Future` is not implemented for `i32` - = note: i32 must be a future or must implement `IntoFuture` to be awaited -note: required by a bound in `MyTrait::{opaque#0}` +note: this method is `async` so it expects a future to be returned --> $DIR/fn-not-async-err.rs:6:5 | LL | async fn foo(&self) -> i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MyTrait::{opaque#0}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. From 1a3214b774f47b2fb8dadf305939f97e20993fe2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 18 Jan 2024 17:28:37 +0000 Subject: [PATCH 575/676] Make sure refinement still works --- .../in-trait/async-example-desugared-boxed.rs | 5 ++++- .../async-example-desugared-boxed.stderr | 22 +++++++++++++++++++ .../async-example-desugared-manual.rs | 7 ++++-- .../async-example-desugared-manual.stderr | 22 +++++++++++++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-manual.stderr diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs index 4008e09998e47..69871d0dca01d 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -4,12 +4,15 @@ use std::future::Future; use std::pin::Pin; -trait MyTrait { +#[allow(async_fn_in_trait)] +pub trait MyTrait { async fn foo(&self) -> i32; } impl MyTrait for i32 { + #[warn(refining_impl_trait)] fn foo(&self) -> Pin + '_>> { + //~^ WARN impl trait in impl method signature does not match trait method signature Box::pin(async { *self }) } } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr new file mode 100644 index 0000000000000..54aba77cc05d0 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -0,0 +1,22 @@ +warning: impl trait in impl method signature does not match trait method signature + --> $DIR/async-example-desugared-boxed.rs:14:22 + | +LL | async fn foo(&self) -> i32; + | --------------------------- return type from trait method defined here +... +LL | fn foo(&self) -> Pin + '_>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate +note: the lint level is defined here + --> $DIR/async-example-desugared-boxed.rs:13:12 + | +LL | #[warn(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ +help: replace the return type so that it matches the trait + | +LL | fn foo(&self) -> impl Future { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs index 75f4ba1d076c6..c6e8f1ae90607 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs @@ -4,11 +4,12 @@ use std::future::Future; use std::task::Poll; -trait MyTrait { +#[allow(async_fn_in_trait)] +pub trait MyTrait { async fn foo(&self) -> i32; } -struct MyFuture; +pub struct MyFuture; impl Future for MyFuture { type Output = i32; fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll { @@ -17,7 +18,9 @@ impl Future for MyFuture { } impl MyTrait for u32 { + #[warn(refining_impl_trait)] fn foo(&self) -> MyFuture { + //~^ WARN impl trait in impl method signature does not match trait method signature MyFuture } } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr new file mode 100644 index 0000000000000..d94afd92c5691 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -0,0 +1,22 @@ +warning: impl trait in impl method signature does not match trait method signature + --> $DIR/async-example-desugared-manual.rs:22:22 + | +LL | async fn foo(&self) -> i32; + | --------------------------- return type from trait method defined here +... +LL | fn foo(&self) -> MyFuture { + | ^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate +note: the lint level is defined here + --> $DIR/async-example-desugared-manual.rs:21:12 + | +LL | #[warn(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ +help: replace the return type so that it matches the trait + | +LL | fn foo(&self) -> impl Future { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +warning: 1 warning emitted + From c94769a9748233559313c532d524f58ebb643b1d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 5 Feb 2024 22:21:40 +0100 Subject: [PATCH 576/676] Clarify order of operations during interning Co-authored-by: Ralf Jung --- compiler/rustc_const_eval/src/interpret/intern.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index c3a53f90e60a0..38e7843761be8 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -148,6 +148,13 @@ pub fn intern_const_alloc_recursive< // better errors. Maybe we should consider doing validation before interning in the future. while let Some(prov) = todo.pop() { let alloc_id = prov.alloc_id(); + // Crucially, we check this *before* checking whether the `alloc_id` + // has already been interned. The point of this check is to ensure that when + // there are multiple pointers to the same allocation, they are *all* immutable. + // Therefore it would be bad if we only checked the first pointer to any given + // allocation. + // (It is likely not possible to actually have multiple pointers to the same allocation, + // so alternatively we could also check that and ICE if there are multiple such pointers.) if intern_kind != InternKind::Promoted && inner_mutability == Mutability::Not && !prov.immutable() From c151ed4764636b380aab6f6edc6e369c4a7a2f58 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 5 Feb 2024 23:19:48 +0000 Subject: [PATCH 577/676] Add test. --- tests/mir-opt/gvn_copy_moves.fn0.GVN.diff | 27 +++++++++++++ tests/mir-opt/gvn_copy_moves.rs | 46 +++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tests/mir-opt/gvn_copy_moves.fn0.GVN.diff create mode 100644 tests/mir-opt/gvn_copy_moves.rs diff --git a/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff new file mode 100644 index 0000000000000..b7463a08d9f3f --- /dev/null +++ b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff @@ -0,0 +1,27 @@ +- // MIR for `fn0` before GVN ++ // MIR for `fn0` after GVN + + fn fn0() -> () { + let mut _0: (); + let mut _1: usize; + let mut _2: [u128; 6]; + let mut _3: ([u128; 6],); + let mut _4: ([u128; 6],); + let mut _5: (); + + bb0: { + _1 = const 1_usize; + _2 = [const 42_u128; 6]; +- _2[_1] = const 1_u128; ++ _2[1 of 2] = const 1_u128; + _3 = (_2,); + _4 = _3; +- _5 = fn1(move (_3.0: [u128; 6]), _4) -> [return: bb1, unwind unreachable]; ++ _5 = fn1(move (_3.0: [u128; 6]), _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_moves.rs b/tests/mir-opt/gvn_copy_moves.rs new file mode 100644 index 0000000000000..d216825e5e689 --- /dev/null +++ b/tests/mir-opt/gvn_copy_moves.rs @@ -0,0 +1,46 @@ +// unit-test: GVN + +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "initial")] +fn fn0() { + // CHECK-LABEL: fn fn0( + mir! { + let a: usize; + let b: [u128; 6]; + let c: ([u128; 6],); + let d: ([u128; 6],); + let x: (); + { + // CHECK: bb0: { + // CHECK-NEXT: _1 = const 1_usize; + // CHECK-NEXT: _2 = [const 42_u128; 6]; + // CHECK-NEXT: _2[1 of 2] = const 1_u128; + // CHECK-NEXT: _3 = (_2,); + // CHECK-NEXT: _4 = _3; + // CHECK-NEXT: _5 = fn1((_3.0: [u128; 6]), _3) + a = 1_usize; + b = [42; 6]; + b[a] = 1; + c = (b,); + d = c; + Call(x = fn1(Move(c.0), d), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + Return() + } + } +} + +#[inline(never)] +fn fn1(a: [u128; 6], mut b: ([u128; 6],)) { + b.0 = [0; 6]; +} + +fn main() { + fn0(); +} + +// EMIT_MIR gvn_copy_moves.fn0.GVN.diff From 6fbd761644932a31457b15f425f87378387fbdc1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 5 Feb 2024 23:21:33 +0000 Subject: [PATCH 578/676] Also turn moves into copies even if through projections. --- compiler/rustc_mir_transform/src/gvn.rs | 4 ++-- tests/mir-opt/gvn_copy_moves.fn0.GVN.diff | 2 +- .../separate_const_switch.identity.SeparateConstSwitch.diff | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 390ec3e1a36ac..07b788526706d 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1228,8 +1228,8 @@ impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> { fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) { if let Operand::Move(place) = *operand - && let Some(local) = place.as_local() - && self.reused_locals.contains(local) + && !place.is_indirect_first_projection() + && self.reused_locals.contains(place.local) { *operand = Operand::Copy(place); } diff --git a/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff index b7463a08d9f3f..b12de636f58b1 100644 --- a/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff +++ b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff @@ -17,7 +17,7 @@ _3 = (_2,); _4 = _3; - _5 = fn1(move (_3.0: [u128; 6]), _4) -> [return: bb1, unwind unreachable]; -+ _5 = fn1(move (_3.0: [u128; 6]), _3) -> [return: bb1, unwind unreachable]; ++ _5 = fn1((_3.0: [u128; 6]), _3) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index e7280f148377c..d273161528464 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -66,7 +66,7 @@ _5 = ((_2 as Break).0: std::result::Result); StorageLive(_6); _6 = _5; - _12 = move ((_5 as Err).0: i32); + _12 = ((_5 as Err).0: i32); _0 = Result::::Err(_12); StorageDead(_6); StorageDead(_2); @@ -83,7 +83,7 @@ } bb4: { - _10 = move ((_1 as Err).0: i32); + _10 = ((_1 as Err).0: i32); StorageLive(_11); _11 = Result::::Err(_10); _2 = ControlFlow::, i32>::Break(move _11); @@ -92,7 +92,7 @@ } bb5: { - _9 = move ((_1 as Ok).0: i32); + _9 = ((_1 as Ok).0: i32); _2 = ControlFlow::, i32>::Continue(_9); goto -> bb3; } From d3214372046eb303ee7c4e569602cd3205975ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 6 Feb 2024 00:37:57 +0100 Subject: [PATCH 579/676] Remove b-naber from the compiler review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 68c863bb919db..eba8e283815c8 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -658,7 +658,6 @@ compiler-team = [ ] compiler-team-contributors = [ "@TaKO8Ki", - "@b-naber", "@nnethercote", "@fmease", ] From 411967c0786495d750a60d1cb67087471bc3684f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 31 Jan 2024 02:37:44 +0100 Subject: [PATCH 580/676] Zip together `place_ty` and `place_validity` --- .../rustc_pattern_analysis/src/usefulness.rs | 79 +++++++++++-------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index bbb68b353e436..246b15ad7d013 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -767,12 +767,6 @@ impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { fn ctor_arity(&self, ctor: &Constructor) -> usize { self.cx.ctor_arity(ctor, self.ty) } - fn ctor_sub_tys( - &'a self, - ctor: &'a Constructor, - ) -> impl Iterator + ExactSizeIterator + Captures<'a> { - self.cx.ctor_sub_tys(ctor, self.ty) - } fn ctors_for_ty(&self) -> Result, Cx::Error> { self.cx.ctors_for_ty(self.ty) } @@ -828,6 +822,32 @@ impl fmt::Display for ValidityConstraint { } } +/// Data about a place under investigation. +struct PlaceInfo { + /// The type of the place. + ty: Cx::Ty, + /// Whether the place is known to contain valid data. + validity: ValidityConstraint, +} + +impl PlaceInfo { + fn specialize<'a>( + &'a self, + cx: &'a Cx, + ctor: &'a Constructor, + ) -> impl Iterator + ExactSizeIterator + Captures<'a> { + let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty); + let ctor_sub_validity = self.validity.specialize(ctor); + ctor_sub_tys.map(move |ty| PlaceInfo { ty, validity: ctor_sub_validity }) + } +} + +impl Clone for PlaceInfo { + fn clone(&self) -> Self { + Self { ty: self.ty.clone(), validity: self.validity } + } +} + /// Represents a pattern-tuple under investigation. // The three lifetimes are: // - 'p coming from the input @@ -1001,10 +1021,9 @@ struct Matrix<'p, Cx: TypeCx> { /// each column must have the same type. Each column corresponds to a place within the /// scrutinee. rows: Vec>, - /// Track the type of each column/place. - place_ty: SmallVec<[Cx::Ty; 2]>, - /// Track for each column/place whether it contains a known valid value. - place_validity: SmallVec<[ValidityConstraint; 2]>, + /// Track info about each place. Each place corresponds to a column in `rows`, and their types + /// must match. + place_info: SmallVec<[PlaceInfo; 2]>, /// Track whether the virtual wildcard row used to compute exhaustiveness is relevant. See top /// of the file for details on relevancy. wildcard_row_is_relevant: bool, @@ -1032,10 +1051,10 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Self { + let place_info = PlaceInfo { ty: scrut_ty, validity: scrut_validity }; let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), - place_ty: smallvec![scrut_ty], - place_validity: smallvec![scrut_validity], + place_info: smallvec![place_info], wildcard_row_is_relevant: true, }; for (row_id, arm) in arms.iter().enumerate() { @@ -1051,11 +1070,11 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { matrix } - fn head_ty(&self) -> Option<&Cx::Ty> { - self.place_ty.first() + fn head_place(&self) -> Option<&PlaceInfo> { + self.place_info.first() } fn column_count(&self) -> usize { - self.place_ty.len() + self.place_info.len() } fn rows( @@ -1083,18 +1102,13 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { ctor: &Constructor, ctor_is_relevant: bool, ) -> 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(); - let ctor_sub_validity = self.place_validity[0].specialize(ctor); - let specialized_place_validity = std::iter::repeat(ctor_sub_validity) - .take(arity) - .chain(self.place_validity[1..].iter().copied()) - .collect(); + let subfield_place_info = self.place_info[0].specialize(pcx.cx, ctor); + let arity = subfield_place_info.len(); + let specialized_place_info = + subfield_place_info.chain(self.place_info[1..].iter().cloned()).collect(); let mut matrix = Matrix { rows: Vec::new(), - place_ty: specialized_place_ty, - place_validity: specialized_place_validity, + place_info: specialized_place_info, wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant, }; for (i, row) in self.rows().enumerate() { @@ -1127,11 +1141,11 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { .map(|row| row.iter().map(|pat| format!("{pat:?}")).collect()) .collect(); pretty_printed_matrix - .push(self.place_validity.iter().map(|validity| format!("{validity}")).collect()); + .push(self.place_info.iter().map(|place| format!("{}", place.validity)).collect()); let column_count = self.column_count(); assert!(self.rows.iter().all(|row| row.len() == column_count)); - assert!(self.place_validity.len() == column_count); + assert!(self.place_info.len() == column_count); let column_widths: Vec = (0..column_count) .map(|col| pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)) .collect(); @@ -1447,7 +1461,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( return Ok(WitnessMatrix::empty()); } - let Some(ty) = matrix.head_ty().cloned() else { + let Some(place) = matrix.head_place() else { // The base case: there are no columns in the matrix. We are morally pattern-matching on (). // A row is useful iff it has no (unguarded) rows above it. let mut useful = true; // Whether the next row is useful. @@ -1467,18 +1481,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( }; }; - debug!("ty: {ty:?}"); - let pcx = &PlaceCtxt { cx: mcx.tycx, ty: &ty }; + let ty = &place.ty.clone(); // Clone it out so we can mutate `matrix` later. + let pcx = &PlaceCtxt { cx: mcx.tycx, ty }; + debug!("ty: {:?}", pcx.ty); let ctors_for_ty = pcx.ctors_for_ty()?; - // Whether the place/column we are inspecting is known to contain valid data. - let place_validity = matrix.place_validity[0]; // We treat match scrutinees of type `!` or `EmptyEnum` differently. let is_toplevel_exception = is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors); // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`). - let empty_arms_are_unreachable = place_validity.is_known_valid() + let empty_arms_are_unreachable = place.validity.is_known_valid() && (is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on() || mcx.tycx.is_min_exhaustive_patterns_feature_on()); From 6cac1c459ec1f2aa7dd31e9b1b90040c906c64f5 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 31 Jan 2024 02:46:10 +0100 Subject: [PATCH 581/676] Track `is_top_level` via `PlaceInfo` --- .../rustc_pattern_analysis/src/usefulness.rs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 246b15ad7d013..1ac984ce67eec 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -828,6 +828,8 @@ struct PlaceInfo { ty: Cx::Ty, /// Whether the place is known to contain valid data. validity: ValidityConstraint, + /// Whether the place is the scrutinee itself or a subplace of it. + is_scrutinee: bool, } impl PlaceInfo { @@ -838,13 +840,17 @@ impl PlaceInfo { ) -> impl Iterator + ExactSizeIterator + Captures<'a> { let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty); let ctor_sub_validity = self.validity.specialize(ctor); - ctor_sub_tys.map(move |ty| PlaceInfo { ty, validity: ctor_sub_validity }) + ctor_sub_tys.map(move |ty| PlaceInfo { + ty, + validity: ctor_sub_validity, + is_scrutinee: false, + }) } } impl Clone for PlaceInfo { fn clone(&self) -> Self { - Self { ty: self.ty.clone(), validity: self.validity } + Self { ty: self.ty.clone(), validity: self.validity, is_scrutinee: self.is_scrutinee } } } @@ -1051,7 +1057,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Self { - let place_info = PlaceInfo { ty: scrut_ty, validity: scrut_validity }; + let place_info = PlaceInfo { ty: scrut_ty, validity: scrut_validity, is_scrutinee: true }; let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), place_info: smallvec![place_info], @@ -1446,11 +1452,10 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( /// - unspecialization, where we lift the results from the previous step into results for this step /// (using `apply_constructor` and by updating `row.useful` for each parent row). /// This is all explained at the top of the file. -#[instrument(level = "debug", skip(mcx, is_top_level), ret)] +#[instrument(level = "debug", skip(mcx), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( mcx: UsefulnessCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, - is_top_level: bool, ) -> Result, Cx::Error> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); @@ -1488,7 +1493,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( // We treat match scrutinees of type `!` or `EmptyEnum` differently. let is_toplevel_exception = - is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors); + place.is_scrutinee && matches!(ctors_for_ty, ConstructorSet::NoConstructors); // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`). let empty_arms_are_unreachable = place.validity.is_known_valid() @@ -1517,7 +1522,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( // Decide what constructors to report. let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); - let always_report_all = is_top_level && !is_integers; + let always_report_all = place.is_scrutinee && !is_integers; // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". let report_individual_missing_ctors = always_report_all || !all_missing; // Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() => @@ -1538,7 +1543,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( 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 witnesses = ensure_sufficient_stack(|| { - compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false) + compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix) })?; // Transform witnesses for `spec_matrix` into witnesses for `matrix`. @@ -1613,8 +1618,7 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>( ) -> 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)?; + let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness(cx, &mut matrix)?; let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column(); let arm_usefulness: Vec<_> = arms From 0ac1195ee0f8cd6d87e654a2312b899883272ec2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 6 Feb 2024 09:51:39 +1100 Subject: [PATCH 582/676] Invert diagnostic lints. That is, change `diagnostic_outside_of_impl` and `untranslatable_diagnostic` from `allow` to `deny`, because more than half of the compiler has be converted to use translated diagnostics. This commit removes more `deny` attributes than it adds `allow` attributes, which proves that this change is warranted. --- compiler/rustc_arena/src/lib.rs | 2 -- compiler/rustc_ast/src/lib.rs | 2 -- compiler/rustc_ast_lowering/src/lib.rs | 2 -- compiler/rustc_ast_passes/src/lib.rs | 2 -- compiler/rustc_ast_pretty/src/lib.rs | 2 -- compiler/rustc_attr/src/lib.rs | 2 -- compiler/rustc_borrowck/src/borrow_set.rs | 2 -- compiler/rustc_borrowck/src/borrowck_errors.rs | 3 +++ compiler/rustc_borrowck/src/constraints/mod.rs | 3 --- compiler/rustc_borrowck/src/consumers.rs | 2 -- compiler/rustc_borrowck/src/dataflow.rs | 2 -- compiler/rustc_borrowck/src/def_use.rs | 2 -- .../rustc_borrowck/src/diagnostics/bound_region_errors.rs | 3 --- .../rustc_borrowck/src/diagnostics/conflict_errors.rs | 3 +++ compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs | 3 +++ .../rustc_borrowck/src/diagnostics/find_all_local_uses.rs | 3 --- compiler/rustc_borrowck/src/diagnostics/find_use.rs | 3 --- compiler/rustc_borrowck/src/diagnostics/move_errors.rs | 3 +++ .../rustc_borrowck/src/diagnostics/mutability_errors.rs | 3 +++ .../rustc_borrowck/src/diagnostics/outlives_suggestion.rs | 3 +++ compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 2 -- compiler/rustc_borrowck/src/diagnostics/region_name.rs | 3 +++ compiler/rustc_borrowck/src/diagnostics/var_name.rs | 3 --- compiler/rustc_borrowck/src/facts.rs | 2 -- compiler/rustc_borrowck/src/location.rs | 2 -- compiler/rustc_borrowck/src/member_constraints.rs | 2 -- compiler/rustc_borrowck/src/nll.rs | 2 -- compiler/rustc_borrowck/src/path_utils.rs | 2 -- compiler/rustc_borrowck/src/place_ext.rs | 2 -- compiler/rustc_borrowck/src/places_conflict.rs | 2 -- .../rustc_borrowck/src/polonius/loan_invalidations.rs | 2 -- compiler/rustc_borrowck/src/polonius/loan_kills.rs | 2 -- compiler/rustc_borrowck/src/prefixes.rs | 2 -- compiler/rustc_borrowck/src/region_infer/dump_mir.rs | 2 -- compiler/rustc_borrowck/src/region_infer/graphviz.rs | 2 -- compiler/rustc_borrowck/src/region_infer/opaque_types.rs | 2 ++ compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs | 2 -- compiler/rustc_borrowck/src/region_infer/values.rs | 2 -- compiler/rustc_borrowck/src/renumber.rs | 2 -- compiler/rustc_borrowck/src/type_check/mod.rs | 2 -- compiler/rustc_borrowck/src/universal_regions.rs | 3 +++ compiler/rustc_borrowck/src/used_muts.rs | 2 -- compiler/rustc_builtin_macros/src/lib.rs | 2 ++ compiler/rustc_codegen_cranelift/src/lib.rs | 2 ++ compiler/rustc_codegen_gcc/src/lib.rs | 2 -- compiler/rustc_codegen_llvm/src/lib.rs | 2 -- compiler/rustc_codegen_ssa/src/lib.rs | 2 ++ compiler/rustc_const_eval/src/lib.rs | 2 +- compiler/rustc_data_structures/src/lib.rs | 2 -- compiler/rustc_driver_impl/src/lib.rs | 2 -- compiler/rustc_error_codes/src/lib.rs | 2 -- compiler/rustc_error_messages/src/lib.rs | 2 -- compiler/rustc_errors/src/lib.rs | 2 ++ compiler/rustc_expand/src/base.rs | 2 -- compiler/rustc_expand/src/lib.rs | 2 +- compiler/rustc_feature/src/lib.rs | 2 -- compiler/rustc_fluent_macro/src/lib.rs | 2 -- compiler/rustc_fs_util/src/lib.rs | 2 -- compiler/rustc_graphviz/src/lib.rs | 2 -- compiler/rustc_hir/src/lib.rs | 2 -- compiler/rustc_hir_analysis/src/lib.rs | 2 ++ compiler/rustc_hir_pretty/src/lib.rs | 2 -- compiler/rustc_hir_typeck/src/lib.rs | 2 ++ compiler/rustc_incremental/src/lib.rs | 2 -- compiler/rustc_index/src/lib.rs | 2 -- compiler/rustc_infer/src/lib.rs | 2 ++ compiler/rustc_interface/src/lib.rs | 2 -- compiler/rustc_lexer/src/lib.rs | 3 +-- compiler/rustc_lint/src/internal.rs | 4 ++-- compiler/rustc_lint/src/lib.rs | 2 -- compiler/rustc_lint/src/lints.rs | 3 ++- compiler/rustc_lint_defs/src/lib.rs | 2 -- compiler/rustc_llvm/src/lib.rs | 2 -- compiler/rustc_log/src/lib.rs | 3 --- compiler/rustc_macros/src/lib.rs | 2 -- compiler/rustc_metadata/src/lib.rs | 2 -- compiler/rustc_middle/src/lib.rs | 4 +++- compiler/rustc_mir_build/src/lib.rs | 3 +++ compiler/rustc_mir_dataflow/src/lib.rs | 2 -- compiler/rustc_mir_transform/src/lib.rs | 2 -- compiler/rustc_monomorphize/src/lib.rs | 2 -- compiler/rustc_parse/src/lib.rs | 4 +++- compiler/rustc_parse_format/src/lib.rs | 2 -- compiler/rustc_passes/src/lib.rs | 2 -- compiler/rustc_pattern_analysis/src/lib.rs | 3 +++ compiler/rustc_privacy/src/lib.rs | 2 -- compiler/rustc_query_impl/src/lib.rs | 2 -- compiler/rustc_query_system/src/lib.rs | 2 -- compiler/rustc_resolve/src/lib.rs | 2 ++ compiler/rustc_serialize/src/lib.rs | 2 -- compiler/rustc_session/src/lib.rs | 2 -- compiler/rustc_span/src/lib.rs | 2 -- compiler/rustc_symbol_mangling/src/lib.rs | 2 -- compiler/rustc_target/src/lib.rs | 2 -- compiler/rustc_trait_selection/src/lib.rs | 2 ++ compiler/rustc_traits/src/lib.rs | 2 -- compiler/rustc_transmute/src/lib.rs | 2 -- compiler/rustc_ty_utils/src/lib.rs | 2 -- compiler/rustc_ty_utils/src/representability.rs | 2 -- compiler/rustc_type_ir/src/lib.rs | 2 -- src/librustdoc/lib.rs | 2 ++ src/tools/clippy/clippy_config/src/lib.rs | 4 +++- src/tools/clippy/clippy_lints/src/lib.rs | 7 ++++++- src/tools/clippy/clippy_utils/src/lib.rs | 8 +++++++- src/tools/clippy/src/driver.rs | 2 ++ src/tools/miri/src/bin/miri.rs | 4 +++- src/tools/miri/src/lib.rs | 4 +++- 107 files changed, 89 insertions(+), 166 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 90ddeec4bc7a4..5cb79d9eea53b 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -22,8 +22,6 @@ #![cfg_attr(test, feature(test))] #![feature(strict_provenance)] #![deny(unsafe_op_in_unsafe_fn)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine. diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 76d838308b461..356e9fef439ed 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -18,8 +18,6 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(stmt_expr_attributes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f26b1331ef388..0c3696074d936 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -35,8 +35,6 @@ #![doc(rust_logo)] #![feature(box_patterns)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index fa6cdd55c3dcb..74d0fff2734fc 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -11,8 +11,6 @@ #![feature(if_let_guard)] #![feature(iter_is_partitioned)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] pub mod ast_validation; mod errors; diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 61617beb86b5a..b9e217a21e39f 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -1,8 +1,6 @@ #![allow(internal_features)] #![feature(rustdoc_internals)] #![doc(rust_logo)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![feature(box_patterns)] mod helpers; diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 3c5bcecddeaa4..dd87a5c4dc384 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -8,8 +8,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 948af03953718..6a683d129ded1 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::path_utils::allow_two_phase_borrow; use crate::place_ext::PlaceExt; use crate::BorrowIndex; diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 6cbcda37f50b8..429bcb74a8efc 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{codes::*, struct_span_code_err, DiagCtxt, DiagnosticBuilder}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index 041ac75ec016e..ff11e4db12133 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use rustc_data_structures::graph::scc::Sccs; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::ConstraintCategory; diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index becfa535a59cc..a58fe2b744701 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This file provides API for compiler consumers. use rustc_hir::def_id::LocalDefId; diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 1bd891bdd685c..bc5bd7879563a 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph::WithSuccessors; use rustc_index::bit_set::BitSet; diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index d0cf339e7ba41..6fd80d005d9e3 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_middle::mir::visit::{ MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, }; diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index bb5335febbf5e..a540fcee871c7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use rustc_errors::DiagnosticBuilder; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index b0b7cc076bab5..226a7ddba6cc5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,5 +1,8 @@ // ignore-tidy-filelength +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use either::Either; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 4f66468a865f8..9627dc5368066 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -1,5 +1,8 @@ //! Print diagnostics to explain why values are borrowed. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs index 2c4d953f011fc..ff4f2bb9614f1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::collections::BTreeSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index 2495613fea1d2..94b17e0a2f99c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::collections::VecDeque; use std::rc::Rc; diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 0a0bb75a2a3a6..126a50c91b494 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3fddf67f55b97..4200bdf453db2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use hir::ExprKind; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_hir as hir; diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index bac1d9dd57f6b..93e28a5f3f3e2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -1,6 +1,9 @@ //! Contains utilities for generating suggestions for borrowck errors related to unsatisfied //! outlives constraints. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_middle::ty::RegionVid; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8c8ca1ead400b..3a16d37b1b1b9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 15e1066e983a9..8d5a6731f9b44 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use std::fmt::{self, Display}; use std::iter; diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 28e07f2a81edd..0479cd8af35e2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use crate::region_infer::RegionInferenceContext; use rustc_index::IndexSlice; use rustc_middle::mir::{Body, Local}; diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index c54e7070478ca..68dc9a6764bfc 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::location::{LocationIndex, LocationTable}; use crate::BorrowIndex; use polonius_engine::AllFacts as PoloniusFacts; diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs index 6f09393169f3d..63e59217e5d7d 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/location.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_index::IndexVec; use rustc_middle::mir::{BasicBlock, Body, Location}; diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs index 842e90080582f..5129b32d492dd 100644 --- a/compiler/rustc_borrowck/src/member_constraints.rs +++ b/compiler/rustc_borrowck/src/member_constraints.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexMap; use rustc_index::{IndexSlice, IndexVec}; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 7ace013975e1b..67237c3adcf20 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! The entry point of the NLL borrow checker. use polonius_engine::{Algorithm, Output}; diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index 2d997dfadf004..d2c1c384e52a8 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; use crate::places_conflict; use crate::AccessDepth; diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index 3d7e8c6ebf330..b59ab7fafa576 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::borrow_set::LocalsStateAtExit; use rustc_hir as hir; use rustc_middle::mir::ProjectionElem; diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 777ebf0d438dc..7e8dba43b715e 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -50,8 +50,6 @@ //! and either equal or disjoint. //! - If we did run out of access, the borrow can access a part of it. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::ArtificialField; use crate::Overlap; use crate::{AccessDepth, Deep, Shallow}; diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 5c9056272cc0d..93aae1a7f9762 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue}; diff --git a/compiler/rustc_borrowck/src/polonius/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/loan_kills.rs index 5df943837025e..53adad5561e60 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_kills.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_kills.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index e9c9709bd1f1a..8bb3dc88b3467 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an //! place are formed by stripping away fields and derefs, except that //! we stop when we reach the deref of a shared reference. [...] " diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index cfbb2766c3397..53541b33c41d1 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! As part of generating the regions, if you enable `-Zdump-mir=nll`, //! we will generate an annotated copy of the MIR that includes the //! state of region inference. This code handles emitting the region diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 408c8390e763c..c103ba3c40709 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This module provides linkage between RegionInferenceContext and //! `rustc_graphviz` traits, specialized to attaching borrowck analysis //! data to rendered labels. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 462b5c8da42c7..636c174e002d2 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -418,6 +418,8 @@ fn check_opaque_type_parameter_valid( .into_iter() .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) .collect(); + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] return Err(tcx .dcx() .struct_span_err(span, "non-defining opaque type use in defining scope") diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs index fe56bd54a3f17..eeb944702a7f9 100644 --- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs +++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::constraints::ConstraintSccIndex; use crate::RegionInferenceContext; use itertools::Itertools; diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index e147f62011db9..b1caaa6388186 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::SparseBitMatrix; diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index a31d39e14cd28..dca8df3280028 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::BorrowckInferCtxt; use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 59c4d9a6c78ca..63b0dea3e2924 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This pass type-checks the MIR to ensure it is not broken. use std::rc::Rc; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index ae8a135f09059..7ffa98f5806a8 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -12,6 +12,9 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 6ac8e1ba7156a..81757a62e5bc5 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxIndexSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 4d7957ef4ddb0..d30ccab239437 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -2,6 +2,8 @@ //! injecting code into the crate before it is lowered to HIR. #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(rustdoc_internals)] #![doc(rust_logo)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 416f87fcc87b3..7c432e9c59051 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -3,6 +3,8 @@ #![cfg_attr(doc, doc(rust_logo))] #![feature(rustc_private)] // Note: please avoid adding other feature gates where possible +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index f8f054db65ede..863b6333bcc29 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -27,8 +27,6 @@ #![recursion_limit="256"] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] extern crate rustc_apfloat; extern crate rustc_ast; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index f4f29078190a1..de96bf477adb7 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -15,8 +15,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(impl_trait_in_assoc_type)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index fc833a3863e40..1afc597a7ef01 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -2,6 +2,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 946a49982aa1a..839cfd8d85acf 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -5,9 +5,9 @@ Rust MIR: a lowered representation of Rust. */ #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] #![feature(rustdoc_internals)] #![doc(rust_logo)] -#![deny(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 563d8501890ce..ef1183e979fdd 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -11,8 +11,6 @@ #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![cfg_attr(not(parallel_compiler), feature(cell_leak))] -#![deny(rustc::diagnostic_outside_of_impl)] -#![deny(rustc::untranslatable_diagnostic)] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 5903c43ae98af..2d40f15dca3a3 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -12,8 +12,6 @@ #![feature(let_chains)] #![feature(panic_update_hook)] #![feature(result_flattening)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 5b2766618fccb..da688e385aa09 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -5,8 +5,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![deny(rustdoc::invalid_codeblock_attributes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] // This higher-order macro defines the error codes that are in use. It is used // in the `rustc_errors` crate. Removed error codes are listed in the comment diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 8fd7c5764797e..e9627007e032f 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -3,8 +3,6 @@ #![feature(lazy_cell)] #![feature(rustc_attrs)] #![feature(type_alias_impl_trait)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b2bd4d8eb956e..ccdad326c6320 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,6 +5,8 @@ // tidy-alphabetical-start #![allow(incomplete_features)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 657e19277a7ed..cfeb31fc4c813 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] - use crate::base::ast::NestedMetaItem; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 2cf6a8df7c5ff..4da86d77dc88f 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -10,7 +10,7 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index cd1d9b13daa15..f1c8f2e2dde5c 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -15,8 +15,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![feature(lazy_cell)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] mod accepted; mod builtin_attrs; diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index fc65d1eb8c4ce..e3784409af8fd 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -4,8 +4,6 @@ #![feature(rustdoc_internals)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(rustc::default_hash_types)] use proc_macro::TokenStream; diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 81d6333814544..3359fef8c1c46 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -1,6 +1,4 @@ #![feature(absolute_path)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use std::ffi::CString; use std::fs; diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index eba3215d93153..43bee5c4be029 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -276,8 +276,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use LabelText::*; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 6c64d802e68f1..aff946ac58081 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -9,8 +9,6 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 454cb97ac148b..9904d8dc5faad 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -55,7 +55,9 @@ This API is completely unstable and subject to change. */ +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9d0c5cb0f32b0..b7709deeb4ad4 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2,8 +2,6 @@ //! the definitions in this file have equivalents in `rustc_ast_pretty`. #![recursion_limit = "256"] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_ast as ast; use rustc_ast::util::parser::{self, AssocOp, Fixity}; diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index deb3ad2edc740..3054a70e6d460 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(try_blocks)] diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 82f02b7d47aac..0729986f32fdf 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -5,8 +5,6 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 854841206b89b..6fcb3a024ab6f 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![cfg_attr( feature = "nightly", feature(extend_one, min_specialization, new_uninit, step_trait, test) diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index e2dd4b49e1a4b..622cdf0c7b895 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -16,6 +16,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(extend_one)] diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 69414a1379515..7d69e49b209f5 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -4,8 +4,6 @@ #![feature(let_chains)] #![feature(thread_spawn_unchecked)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index f6c9289b529c7..ca84e930c2439 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -18,8 +18,7 @@ //! lexeme types. //! //! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] + // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index eb2490a47d09d..516df14c8943a 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -345,7 +345,7 @@ declare_tool_lint! { /// /// More details on translatable diagnostics can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html). pub rustc::UNTRANSLATABLE_DIAGNOSTIC, - Allow, + Deny, "prevent creation of diagnostics which cannot be translated", report_in_external_macro: true } @@ -357,7 +357,7 @@ declare_tool_lint! { /// /// More details on diagnostics implementations can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html). pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL, - Allow, + Deny, "prevent creation of diagnostics outside of `IntoDiagnostic`/`AddToDiagnostic` impls", report_in_external_macro: true } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 1d9ce10bcaf38..9a7a5c0c6df00 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -37,8 +37,6 @@ #![cfg_attr(not(bootstrap), feature(trait_upcasting))] #![feature(min_specialization)] #![feature(rustc_attrs)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index f916deb4a46d1..c0d76b4e27eeb 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,5 +1,6 @@ -#![allow(rustc::untranslatable_diagnostic)] #![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use std::num::NonZeroU32; use crate::errors::RequestedLevel; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index eed35326c4501..8b7e82d2113f8 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,6 +1,4 @@ #![feature(min_specialization)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index ca0aec71052d0..6a570c97c8888 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index e3464cb8a2df6..1a78f9f0f86e5 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -38,9 +38,6 @@ //! debugging, you can make changes inside those crates and quickly run main.rs //! to read the debug logs. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::env::{self, VarError}; use std::fmt::{self, Display}; use std::io::{self, IsTerminal}; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 9e85a59b5b92b..af65c908ee66b 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -6,8 +6,6 @@ #![feature(proc_macro_span)] #![feature(proc_macro_tracked_env)] #![allow(rustc::default_hash_types)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] use synstructure::decl_derive; diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 471425e80174f..2e7130f356579 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -15,8 +15,6 @@ #![feature(try_blocks)] #![feature(never_type)] #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] extern crate proc_macro; diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index ddfb2ece39f10..515b6703b1e36 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -57,8 +57,10 @@ #![feature(const_option)] #![feature(ptr_alignment_type)] #![feature(macro_metavar_expr)] -#![allow(rustc::potential_query_instability)] #![allow(internal_features)] +#![allow(rustc::potential_query_instability)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #[macro_use] extern crate bitflags; diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index a3d88b1269686..43e44b47e3f96 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -1,6 +1,9 @@ //! Construction of MIR from HIR. //! //! This crate also contains the match exhaustiveness and usefulness checking. + +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(box_patterns)] diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 23111cc319956..a4b58e5bfc128 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -4,8 +4,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 69f93fa3a0e21..fe828f535e00d 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(const_type_name)] diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index b0cfa3568cad7..7f36ae91f1a03 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,8 +1,6 @@ #![feature(array_windows)] #![feature(is_sorted)] #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index d5fa11086872f..5bd8bb72bd665 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,11 +1,13 @@ //! The main parser interface. +#![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(array_windows)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![allow(internal_features)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index d76ee161da6fd..0b65f400825ae 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -9,8 +9,6 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))) )] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 862b76b1f6048..064af5aec35aa 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -12,8 +12,6 @@ #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 3d0eb117d174f..fe347231e121c 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -1,5 +1,8 @@ //! Analysis of patterns, notably match exhaustiveness checking. +#![allow(rustc::untranslatable_diagnostic)] +#![allow(rustc::diagnostic_outside_of_impl)] + pub mod constructor; #[cfg(feature = "rustc")] pub mod errors; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a64b06e70d6bc..a284d145a4ddb 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -5,8 +5,6 @@ #![feature(associated_type_defaults)] #![feature(try_blocks)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 818a67a7debf6..0fe5b9c664a35 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -6,8 +6,6 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] #![allow(rustc::potential_query_instability, unused_parens)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 9b66b9a48d905..416f556f57d28 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -4,8 +4,6 @@ #![feature(min_specialization)] #![feature(let_chains)] #![allow(rustc::potential_query_instability, internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9d09d060b59b8..5fb9117f0c857 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -17,7 +17,9 @@ #![feature(let_chains)] #![feature(rustc_attrs)] #![allow(rustdoc::private_intra_doc_links)] +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 9c34aa9395764..95833f532f4d8 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -17,8 +17,6 @@ #![feature(ptr_sub_ptr)] #![cfg_attr(test, feature(test))] #![allow(rustc::internal)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] pub use self::serialize::{Decodable, Decoder, Encodable, Encoder}; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 0d6328fbb071c..58e1394c09071 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -4,8 +4,6 @@ #![feature(rustc_attrs)] #![feature(map_many_mut)] #![feature(iter_intersperse)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ea6766ea583be..5f2d4ae2b8c2f 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -17,8 +17,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![deny(rustc::diagnostic_outside_of_impl)] -#![deny(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 362aaca63642e..02bb1fde75c1b 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -91,8 +91,6 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index bffb3681f1309..b19c5b6f28f08 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -17,8 +17,6 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] #![feature(step_trait)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5ec45212bc791..053ecfc681ceb 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -14,6 +14,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index c7916ec60bba2..e73bbf6048ece 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -1,7 +1,5 @@ //! Queries that are independent from the main solver code. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index c80389a3a4d52..ac4f67d1b5565 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -1,8 +1,6 @@ #![feature(alloc_layout_extra)] #![feature(never_type)] #![allow(dead_code, unused_variables)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 51acb99d29b58..411099e3d5af8 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -15,8 +15,6 @@ #![feature(iterator_try_collect)] #![feature(let_chains)] #![feature(never_type)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 3aaa2e73bb805..70f1f099688b8 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -1,5 +1,3 @@ -#![allow(rustc::untranslatable_diagnostic, rustc::diagnostic_outside_of_impl)] - use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_middle::query::Providers; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 83efbfb855f91..f498c5531fcff 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -2,8 +2,6 @@ feature = "nightly", feature(associated_type_defaults, min_specialization, never_type, rustc_attrs) )] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(rustc::usage_of_ty_tykind)] #![cfg_attr(feature = "nightly", allow(internal_features))] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8c10f14116a0c..849127616ef62 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -18,7 +18,9 @@ #![recursion_limit = "256"] #![warn(rustc::internal)] #![allow(clippy::collapsible_if, clippy::collapsible_else_if)] +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] extern crate thin_vec; #[macro_use] diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs index 533e375a3104c..5449feed090a9 100644 --- a/src/tools/clippy/clippy_config/src/lib.rs +++ b/src/tools/clippy/clippy_config/src/lib.rs @@ -4,7 +4,9 @@ #![allow( clippy::must_use_candidate, clippy::missing_panics_doc, - rustc::untranslatable_diagnostic_trivial + rustc::diagnostic_outside_of_impl, + rustc::untranslatable_diagnostic, + rustc::untranslatable_diagnostic_trivial, )] extern crate rustc_ast; diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index feb4d188f3978..f6608b229539a 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -10,7 +10,12 @@ #![feature(stmt_expr_attributes)] #![recursion_limit = "512"] #![cfg_attr(feature = "deny-warnings", deny(warnings))] -#![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)] +#![allow( + clippy::missing_docs_in_private_items, + clippy::must_use_candidate, + rustc::diagnostic_outside_of_impl, + rustc::untranslatable_diagnostic, +)] #![warn(trivial_casts, trivial_numeric_casts)] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 4e499ff4cc612..36034861df5b9 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -8,7 +8,13 @@ #![feature(assert_matches)] #![recursion_limit = "512"] #![cfg_attr(feature = "deny-warnings", deny(warnings))] -#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] +#![allow( + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::must_use_candidate, + rustc::diagnostic_outside_of_impl, + rustc::untranslatable_diagnostic, +)] // warn on the same lints as `clippy_lints` #![warn(trivial_casts, trivial_numeric_casts)] // warn on lints, that are included in `rust-lang/rust`s bootstrap diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index b944a299256c2..1b159f5937a28 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -1,3 +1,5 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(rustc_private)] #![feature(let_chains)] #![feature(lazy_cell)] diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index e8e10f64ad295..de7a4b79d26ff 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -2,7 +2,9 @@ #![allow( clippy::manual_range_contains, clippy::useless_format, - clippy::field_reassign_with_default + clippy::field_reassign_with_default, + rustc::diagnostic_outside_of_impl, + rustc::untranslatable_diagnostic, )] extern crate rustc_data_structures; diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 057b883a3bf9e..94fb746484c6e 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -33,8 +33,10 @@ clippy::bool_to_int_with_if, clippy::box_default, clippy::needless_question_mark, + rustc::diagnostic_outside_of_impl, // We are not implementing queries here so it's fine - rustc::potential_query_instability + rustc::potential_query_instability, + rustc::untranslatable_diagnostic, )] #![warn( rust_2018_idioms, From b2bb51734cd97682cf2124e70ebbb73a3304b6b0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jan 2024 17:18:08 +0000 Subject: [PATCH 583/676] Make sure that async closures (and fns) only capture their parent callable's parameters by move, and nothing else --- compiler/rustc_ast_lowering/src/item.rs | 9 ++-- compiler/rustc_hir_typeck/src/upvar.rs | 51 +++++++++++++++++++ .../async-borrowck-escaping-closure-error.rs | 2 +- ...ync-borrowck-escaping-closure-error.stderr | 21 ++++++++ .../issue-74072-lifetime-name-annotations.rs | 2 + ...sue-74072-lifetime-name-annotations.stderr | 49 ++++++++++++++++-- ...021-incompatible-closure-captures-96258.rs | 2 +- ...incompatible-closure-captures-96258.stderr | 27 +--------- 8 files changed, 127 insertions(+), 36 deletions(-) create mode 100644 tests/ui/async-await/async-borrowck-escaping-closure-error.stderr diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 6b772c1295f55..a122b4c51133c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1278,10 +1278,11 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let closure_id = coroutine_kind.closure_id(); let coroutine_expr = self.make_desugared_coroutine_expr( - // FIXME(async_closures): This should only move locals, - // and not upvars. Capturing closure upvars by ref doesn't - // work right now anyways, so whatever. - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + // The default capture mode here is by-ref. Later on during upvar analysis, + // we will force the captured arguments to by-move, but for async closures, + // we want to make sure that we avoid unnecessarily moving captures, or else + // all async closures would default to `FnOnce` as their calling mode. + CaptureBy::Ref, closure_id, return_type_hint, body_span, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 82c5e566f161c..864acf51025b5 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -200,6 +200,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { capture_information: Default::default(), fake_reads: Default::default(), }; + + // As noted in `lower_coroutine_body_with_moved_arguments`, we default the capture mode + // to `ByRef` for the `async {}` block internal to async fns/closure. This means + // that we would *not* be moving all of the parameters into the async block by default. + // + // We force all of these arguments to be captured by move before we do expr use analysis. + // + // FIXME(async_closures): This could be cleaned up. It's a bit janky that we're just + // moving all of the `LocalSource::AsyncFn` locals here. + if let Some(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Fn | hir::CoroutineSource::Closure, + )) = self.tcx.coroutine_kind(closure_def_id) + { + let hir::ExprKind::Block(block, _) = body.value.kind else { + bug!(); + }; + for stmt in block.stmts { + let hir::StmtKind::Local(hir::Local { + init: Some(init), + source: hir::LocalSource::AsyncFn, + pat, + .. + }) = stmt.kind + else { + bug!(); + }; + let hir::PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), _, _, _) = + pat.kind + else { + // Complex pattern, skip the non-upvar local. + continue; + }; + let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = init.kind else { + bug!(); + }; + let hir::def::Res::Local(local_id) = path.res else { + bug!(); + }; + let place = self.place_for_root_variable(closure_def_id, local_id); + delegate.capture_information.push(( + place, + ty::CaptureInfo { + capture_kind_expr_id: Some(init.hir_id), + path_expr_id: Some(init.hir_id), + capture_kind: UpvarCapture::ByValue, + }, + )); + } + } + euv::ExprUseVisitor::new( &mut delegate, &self.infcx, diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs index f8ff9186842b8..c02bac2d7dd49 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -1,10 +1,10 @@ // edition:2018 -// check-pass #![feature(async_closure)] fn foo() -> Box> { let x = 0u32; Box::new((async || x)()) + //~^ ERROR closure may outlive the current function, but it borrows `x`, which is owned by the current function } fn main() { diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr new file mode 100644 index 0000000000000..87851e1ae5be5 --- /dev/null +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-borrowck-escaping-closure-error.rs:6:15 + | +LL | Box::new((async || x)()) + | ^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/async-borrowck-escaping-closure-error.rs:6:5 + | +LL | Box::new((async || x)()) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | Box::new((async move || x)()) + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs index 95683241aba26..2d453e7891e5f 100644 --- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs @@ -12,6 +12,7 @@ pub async fn async_fn(x: &mut i32) -> &i32 { pub fn async_closure(x: &mut i32) -> impl Future { (async move || { + //~^ captured variable cannot escape `FnMut` closure body let y = &*x; *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed y @@ -20,6 +21,7 @@ pub fn async_closure(x: &mut i32) -> impl Future { pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future { (async move || -> &i32 { + //~^ captured variable cannot escape `FnMut` closure body let y = &*x; *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed y diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr index 628ba1a481893..9120d78164e88 100644 --- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr @@ -11,7 +11,7 @@ LL | y | - returning this value requires that `*x` is borrowed for `'1` error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:16:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:17:9 | LL | let y = &*x; | --- `*x` is borrowed here @@ -22,11 +22,32 @@ LL | y LL | })() | - return type of async closure is &'1 i32 +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-74072-lifetime-name-annotations.rs:14:20 + | +LL | pub fn async_closure(x: &mut i32) -> impl Future { + | - variable defined here +LL | (async move || { + | __________________-_^ + | | | + | | inferred to be a `FnMut` closure +LL | | +LL | | let y = &*x; + | | - variable captured here +LL | | *x += 1; +LL | | y +LL | | })() + | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:24:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:26:9 | LL | (async move || -> &i32 { | - let's call the lifetime of this reference `'1` +LL | LL | let y = &*x; | --- `*x` is borrowed here LL | *x += 1; @@ -34,8 +55,28 @@ LL | *x += 1; LL | y | - returning this value requires that `*x` is borrowed for `'1` +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-74072-lifetime-name-annotations.rs:23:28 + | +LL | pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future { + | - variable defined here +LL | (async move || -> &i32 { + | __________________________-_^ + | | | + | | inferred to be a `FnMut` closure +LL | | +LL | | let y = &*x; + | | - variable captured here +LL | | *x += 1; +LL | | y +LL | | })() + | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:32:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:34:9 | LL | let y = &*x; | --- `*x` is borrowed here @@ -46,6 +87,6 @@ LL | y LL | } | - return type of async block is &'1 i32 -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs index a9d678c1e6aff..66a432be35737 100644 --- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs @@ -9,7 +9,7 @@ impl Numberer { //~^ ERROR `async fn` is not permitted in Rust 2015 interval: Duration, //~^ ERROR cannot find type `Duration` in this scope - ) -> Numberer { //~WARN: changes to closure capture in Rust 2021 + ) -> Numberer { Numberer {} } } diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr index 71e9e7602e8e7..60433e1c28467 100644 --- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr @@ -18,32 +18,7 @@ help: consider importing this struct LL + use std::time::Duration; | -warning: changes to closure capture in Rust 2021 will affect drop order - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:12:19 - | -LL | interval: Duration, - | -------- in Rust 2018, this causes the closure to capture `interval`, but in Rust 2021, it has no effect -LL | -LL | ) -> Numberer { - | _________________-_^ - | | | - | | in Rust 2018, `interval` is dropped here along with the closure, but in Rust 2021 `interval` is not part of the closure -LL | | Numberer {} -LL | | } - | |_____^ - | - = note: for more information, see -note: the lint level is defined here - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:1:9 - | -LL | #![warn(rust_2021_incompatible_closure_captures)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: add a dummy let to cause `interval` to be fully captured - | -LL | ) -> Numberer { let _ = &interval; - | ++++++++++++++++++ - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors Some errors have detailed explanations: E0412, E0670. For more information about an error, try `rustc --explain E0412`. From a20421734bb41437598aa3a959ed20441c3fb7f3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jan 2024 17:30:02 +0000 Subject: [PATCH 584/676] Make async closures directly lower to ClosureKind::CoroutineClosure --- compiler/rustc_ast_lowering/messages.ftl | 3 - compiler/rustc_ast_lowering/src/errors.rs | 7 -- compiler/rustc_ast_lowering/src/expr.rs | 27 ++---- compiler/rustc_ast_lowering/src/item.rs | 4 +- compiler/rustc_ast_lowering/src/lib.rs | 3 +- .../src/diagnostics/conflict_errors.rs | 23 +++-- .../rustc_borrowck/src/diagnostics/mod.rs | 4 +- .../src/diagnostics/region_name.rs | 15 +++- compiler/rustc_hir/src/hir.rs | 5 ++ .../src/collect/generics_of.rs | 1 + compiler/rustc_hir_typeck/src/closure.rs | 6 +- .../error_reporting/type_err_ctxt_ext.rs | 83 ++++++++++--------- 12 files changed, 93 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 8615016cda599..cee6525a86a5d 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -117,9 +117,6 @@ ast_lowering_never_pattern_with_guard = a guard on a never pattern will never be run .suggestion = remove this guard -ast_lowering_not_supported_for_lifetime_binder_async_closure = - `for<...>` binders on `async` closures are not currently supported - ast_lowering_previously_used_here = previously used here ast_lowering_register1 = register `{$reg1_name}` diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 51bb8a96fad26..afd156bd6f11b 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -326,13 +326,6 @@ pub struct MisplacedRelaxTraitBound { pub span: Span, } -#[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_not_supported_for_lifetime_binder_async_closure)] -pub struct NotSupportedForLifetimeBinderAsyncClosure { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(ast_lowering_match_arm_with_no_body)] pub struct MatchArmWithNoBody { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0ad4a59c17eb1..2241b4cd8e504 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -2,8 +2,7 @@ use super::errors::{ AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters, FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody, - NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, - UnderscoreExprLhsAssign, + NeverPatternWithBody, NeverPatternWithGuard, UnderscoreExprLhsAssign, }; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; @@ -1026,30 +1025,21 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir> { - if let &ClosureBinder::For { span, .. } = binder { - self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); - } - let (binder_clause, generic_params) = self.lower_closure_binder(binder); let body = self.with_new_scopes(fn_decl_span, |this| { + let inner_decl = + FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; + // Transform `async |x: u8| -> X { ... }` into // `|x: u8| || -> X { ... }`. let body_id = this.lower_body(|this| { - let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output { - let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock); - Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx))) - } else { - None - }; - let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( - decl, + &inner_decl, |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), body.span, coroutine_kind, hir::CoroutineSource::Closure, - async_ret_ty, ); let hir_id = this.lower_node_id(coroutine_kind.closure_id()); @@ -1060,15 +1050,12 @@ impl<'hir> LoweringContext<'_, 'hir> { body_id }); - let outer_decl = - FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. let fn_decl = - self.lower_fn_decl(&outer_decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); + self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { def_id: self.local_def_id(closure_id), @@ -1079,7 +1066,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body, fn_decl_span: self.lower_span(fn_decl_span), fn_arg_span: Some(self.lower_span(fn_arg_span)), - kind: hir::ClosureKind::Closure, + kind: hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async), constness: hir::Constness::NotConst, }); hir::ExprKind::Closure(c) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a122b4c51133c..f347b2ec81b78 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1086,7 +1086,6 @@ impl<'hir> LoweringContext<'_, 'hir> { body.span, coroutine_kind, hir::CoroutineSource::Fn, - None, ); // FIXME(async_fn_track_caller): Can this be moved above? @@ -1108,7 +1107,6 @@ impl<'hir> LoweringContext<'_, 'hir> { body_span: Span, coroutine_kind: CoroutineKind, coroutine_source: hir::CoroutineSource, - return_type_hint: Option>, ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) { let mut parameters: Vec> = Vec::new(); let mut statements: Vec> = Vec::new(); @@ -1284,7 +1282,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // all async closures would default to `FnOnce` as their calling mode. CaptureBy::Ref, closure_id, - return_type_hint, + None, body_span, desugaring_kind, coroutine_source, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f26b1331ef388..0ea7d109182c3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -33,6 +33,7 @@ #![allow(internal_features)] #![feature(rustdoc_internals)] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(let_chains)] #![deny(rustc::untranslatable_diagnostic)] @@ -296,7 +297,6 @@ enum ImplTraitPosition { Path, Variable, Trait, - AsyncBlock, Bound, Generic, ExternFnParam, @@ -323,7 +323,6 @@ impl std::fmt::Display for ImplTraitPosition { ImplTraitPosition::Path => "paths", ImplTraitPosition::Variable => "the type of variable bindings", ImplTraitPosition::Trait => "traits", - ImplTraitPosition::AsyncBlock => "async blocks", ImplTraitPosition::Bound => "bounds", ImplTraitPosition::Generic => "generics", ImplTraitPosition::ExternFnParam => "`extern fn` parameters", diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index b0b7cc076bab5..6debb3362b04c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -858,7 +858,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span }, - hir::ClosureKind::Closure => MoveUseInClosure { var_span }, + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { + MoveUseInClosure { var_span } + } } }); @@ -905,7 +907,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { hir::ClosureKind::Coroutine(_) => { BorrowUsePlaceCoroutine { place: desc_place, var_span, is_single_var: true } } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true } } } @@ -1056,7 +1058,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { var_span, is_single_var: true, }, - hir::ClosureKind::Closure => BorrowUsePlaceClosure { + hir::ClosureKind::Closure + | hir::ClosureKind::CoroutineClosure(_) => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true, @@ -1140,7 +1143,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { var_span, is_single_var: false, }, - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false } } } @@ -1158,7 +1161,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { hir::ClosureKind::Coroutine(_) => { FirstBorrowUsePlaceCoroutine { place: borrow_place_desc, var_span } } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span } } } @@ -1175,7 +1178,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { hir::ClosureKind::Coroutine(_) => { SecondBorrowUsePlaceCoroutine { place: desc_place, var_span } } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { SecondBorrowUsePlaceClosure { place: desc_place, var_span } } } @@ -2942,7 +2945,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, - hir::ClosureKind::Closure => BorrowUseInClosure { var_span }, + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { + BorrowUseInClosure { var_span } + } } }); @@ -2958,7 +2963,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, - hir::ClosureKind::Closure => BorrowUseInClosure { var_span }, + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { + BorrowUseInClosure { var_span } + } } }); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index b35d4e16eccb0..59f3aa706edea 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -614,7 +614,7 @@ impl UseSpans<'_> { PartialAssignment => AssignPartInCoroutine { path_span }, }); } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { err.subdiagnostic(match action { Borrow => BorrowInClosure { path_span }, MatchOn | Use => UseInClosure { path_span }, @@ -1253,7 +1253,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { hir::ClosureKind::Coroutine(_) => { CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial } } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial } } }) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 15e1066e983a9..fc52306e10d0b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -692,7 +692,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Async, hir::CoroutineSource::Closure, - )) => " of async closure", + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => { + " of async closure" + } hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Async, @@ -719,7 +722,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Gen, hir::CoroutineSource::Closure, - )) => " of gen closure", + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => { + " of gen closure" + } hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Gen, @@ -743,7 +749,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::AsyncGen, hir::CoroutineSource::Closure, - )) => " of async gen closure", + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::AsyncGen) => { + " of async gen closure" + } hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::AsyncGen, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index de1b28acb1267..539ab5464e961 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -952,6 +952,11 @@ pub enum ClosureKind { /// usage (e.g. `let x = || { yield (); }`) or from a desugared expression /// (e.g. `async` and `gen` blocks). Coroutine(CoroutineKind), + /// This is a coroutine-closure, which is a special sugared closure that + /// returns one of the sugared coroutine (`async`/`gen`/`async gen`). It + /// additionally allows capturing the coroutine's upvars by ref, and therefore + /// needs to be specially treated during analysis and borrowck. + CoroutineClosure(CoroutineDesugaring), } /// A block of statements `{ .. }`, which may have a label (in this case the diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c29d413184304..d7e91673c7a29 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -349,6 +349,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { ClosureKind::Coroutine(_) => { &["", "", "", "", ""][..] } + ClosureKind::CoroutineClosure(_) => todo!(), }; params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index f51cc97b45deb..18dff5188af94 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -192,6 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(CoroutineTypes { resume_ty, yield_ty }), ) } + hir::ClosureKind::CoroutineClosure(_) => todo!(), }; check_fn( @@ -690,7 +691,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _, )) | hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) - | hir::ClosureKind::Closure => astconv.ty_infer(None, decl.output.span()), + | hir::ClosureKind::Closure + | hir::ClosureKind::CoroutineClosure(_) => { + astconv.ty_infer(None, decl.output.span()) + } }, }; 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 a8715b0764f0a..d57d9f58333c9 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 @@ -1924,45 +1924,50 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str { match kind { hir::ClosureKind::Closure => "a closure", - hir::ClosureKind::Coroutine(kind) => match kind { - hir::CoroutineKind::Coroutine(_) => "a coroutine", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Block, - ) => "an async block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Fn, - ) => "an async function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Closure, - ) => "an async closure", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Block, - ) => "an async gen block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Fn, - ) => "an async gen function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Closure, - ) => "an async gen closure", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Block, - ) => "a gen block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Fn, - ) => "a gen function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Closure, - ) => "a gen closure", - }, + hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => "a coroutine", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Block, + )) => "an async block", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Fn, + )) => "an async function", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure, + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => { + "an async closure" + } + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Block, + )) => "an async gen block", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Fn, + )) => "an async gen function", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Closure, + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::AsyncGen) => { + "an async gen closure" + } + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Block, + )) => "a gen block", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Fn, + )) => "a gen function", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Closure, + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => "a gen closure", } } From c567eddec2c628d4f13707866731e1b2013ad236 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jan 2024 18:01:56 +0000 Subject: [PATCH 585/676] Add CoroutineClosure to TyKind, AggregateKind, UpvarArgs --- .../src/diagnostics/mutability_errors.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 10 +- compiler/rustc_borrowck/src/path_utils.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 33 ++++- compiler/rustc_codegen_gcc/src/type_of.rs | 2 +- compiler/rustc_codegen_llvm/src/type_of.rs | 2 +- .../src/debuginfo/type_names.rs | 6 +- .../src/const_eval/valtrees.rs | 2 + .../src/interpret/eval_context.rs | 1 + .../src/interpret/intrinsics.rs | 1 + .../src/interpret/validity.rs | 1 + .../src/transform/validate.rs | 22 ++++ .../rustc_const_eval/src/util/type_name.rs | 1 + compiler/rustc_hir/src/hir.rs | 1 + .../src/coherence/inherent_impls.rs | 1 + .../src/coherence/orphan.rs | 1 + .../src/collect/generics_of.rs | 8 +- .../src/variance/constraints.rs | 4 +- compiler/rustc_hir_typeck/src/callee.rs | 12 +- compiler/rustc_hir_typeck/src/cast.rs | 1 + .../rustc_hir_typeck/src/method/suggest.rs | 1 + compiler/rustc_hir_typeck/src/upvar.rs | 22 ++-- .../src/infer/canonical/canonicalizer.rs | 1 + .../src/infer/error_reporting/mod.rs | 10 +- .../infer/error_reporting/need_type_info.rs | 5 +- .../infer/error_reporting/note_and_explain.rs | 7 +- compiler/rustc_infer/src/infer/mod.rs | 10 +- .../rustc_infer/src/infer/opaque_types.rs | 11 ++ .../src/infer/outlives/components.rs | 5 + compiler/rustc_lint/src/types.rs | 1 + compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 3 +- compiler/rustc_middle/src/mir/syntax.rs | 1 + compiler/rustc_middle/src/mir/tcx.rs | 3 + compiler/rustc_middle/src/mir/visit.rs | 6 + compiler/rustc_middle/src/ty/context.rs | 1 + compiler/rustc_middle/src/ty/error.rs | 2 +- compiler/rustc_middle/src/ty/fast_reject.rs | 7 +- compiler/rustc_middle/src/ty/flags.rs | 16 +++ compiler/rustc_middle/src/ty/generic_args.rs | 10 +- compiler/rustc_middle/src/ty/layout.rs | 6 + compiler/rustc_middle/src/ty/print/mod.rs | 1 + compiler/rustc_middle/src/ty/print/pretty.rs | 42 +++++++ compiler/rustc_middle/src/ty/relate.rs | 7 ++ .../rustc_middle/src/ty/structural_impls.rs | 4 + compiler/rustc_middle/src/ty/sty.rs | 116 +++++++++++++++++- compiler/rustc_middle/src/ty/util.rs | 15 ++- compiler/rustc_middle/src/ty/walk.rs | 1 + .../src/build/expr/as_rvalue.rs | 3 + compiler/rustc_mir_build/src/build/mod.rs | 2 +- .../rustc_mir_dataflow/src/elaborate_drops.rs | 3 + .../src/move_paths/builder.rs | 8 +- .../src/abort_unwinding_calls.rs | 1 + .../rustc_mir_transform/src/check_unsafety.rs | 4 +- .../src/dataflow_const_prop.rs | 1 + .../src/ffi_unwind_calls.rs | 1 + compiler/rustc_mir_transform/src/gvn.rs | 11 +- .../rustc_mir_transform/src/remove_zsts.rs | 1 + .../src/canonicalizer.rs | 3 +- compiler/rustc_passes/src/liveness.rs | 5 + compiler/rustc_pattern_analysis/src/rustc.rs | 3 +- compiler/rustc_privacy/src/lib.rs | 1 + .../rustc_smir/src/rustc_smir/convert/mir.rs | 3 + .../rustc_smir/src/rustc_smir/convert/ty.rs | 1 + compiler/rustc_symbol_mangling/src/legacy.rs | 7 +- .../src/typeid/typeid_itanium_cxx_abi.rs | 8 +- compiler/rustc_symbol_mangling/src/v0.rs | 1 + .../src/solve/assembly/mod.rs | 5 +- .../src/solve/assembly/structural_traits.rs | 9 ++ .../src/solve/normalizes_to/mod.rs | 2 + .../src/solve/trait_goals.rs | 3 +- .../src/traits/coherence.rs | 2 +- .../error_reporting/type_err_ctxt_ext.rs | 6 +- .../src/traits/project.rs | 2 + .../src/traits/query/dropck_outlives.rs | 20 +++ .../src/traits/select/candidate_assembly.rs | 18 ++- .../src/traits/select/mod.rs | 9 ++ .../src/traits/structural_match.rs | 3 + .../rustc_trait_selection/src/traits/wf.rs | 8 ++ compiler/rustc_ty_utils/src/instance.rs | 1 + compiler/rustc_ty_utils/src/layout.rs | 11 ++ compiler/rustc_ty_utils/src/needs_drop.rs | 6 + compiler/rustc_ty_utils/src/ty.rs | 4 +- compiler/rustc_type_ir/src/ty_kind.rs | 28 +++-- src/librustdoc/clean/mod.rs | 1 + .../passes/collect_intra_doc_links.rs | 1 + .../clippy/clippy_lints/src/dereference.rs | 1 + .../clippy/clippy_lints/src/utils/author.rs | 3 + .../clippy/tests/ui/author/blocks.stdout | 4 +- .../internal-lints/ty_tykind_usage.rs | 1 + .../internal-lints/ty_tykind_usage.stderr | 36 +++--- 91 files changed, 579 insertions(+), 101 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3fddf67f55b97..55649ec2f1645 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1472,7 +1472,7 @@ fn suggest_ampmut<'tcx>( } fn is_closure_or_coroutine(ty: Ty<'_>) -> bool { - ty.is_closure() || ty.is_coroutine() + ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() } /// Given a field that needs to be mutable, returns a span where the " mut " could go. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 8b5e548345c97..eaf9fc4583720 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1303,7 +1303,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // moved into the closure and subsequently used by the closure, // in order to populate our used_mut set. match **aggregate_kind { - AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) => { + AggregateKind::Closure(def_id, _) + | AggregateKind::CoroutineClosure(def_id, _) + | AggregateKind::Coroutine(def_id, _) => { let def_id = def_id.expect_local(); let BorrowCheckResult { used_mut_upvars, .. } = self.infcx.tcx.mir_borrowck(def_id); @@ -1609,6 +1611,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -1633,7 +1636,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; } } - ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (), + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(_, _) + | ty::Tuple(_) => (), ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index 2d997dfadf004..4cfde47664eee 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -164,7 +164,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>( match place_ref.last_projection() { Some((place_base, ProjectionElem::Field(field, _ty))) => { let base_ty = place_base.ty(body, tcx).ty; - if (base_ty.is_closure() || base_ty.is_coroutine()) + if (base_ty.is_closure() || base_ty.is_coroutine() || base_ty.is_coroutine_closure()) && (!by_ref || upvars[field.index()].is_by_ref()) { Some(field) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 59c4d9a6c78ca..90a9844fda9e4 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -808,6 +808,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }), }; } + ty::CoroutineClosure(_, args) => { + return match args.as_coroutine_closure().upvar_tys().get(field.index()) { + Some(&ty) => Ok(ty), + None => Err(FieldAccessError::OutOfRange { + field_count: args.as_coroutine_closure().upvar_tys().len(), + }), + }; + } ty::Coroutine(_, args) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. @@ -1875,6 +1883,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }), } } + AggregateKind::CoroutineClosure(_, args) => { + match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), + None => Err(FieldAccessError::OutOfRange { + field_count: args.as_coroutine_closure().upvar_tys().len(), + }), + } + } AggregateKind::Array(ty) => Ok(ty), AggregateKind::Tuple => { unreachable!("This should have been covered in check_rvalues"); @@ -2478,6 +2494,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { AggregateKind::Tuple => None, AggregateKind::Closure(_, _) => None, AggregateKind::Coroutine(_, _) => None, + AggregateKind::CoroutineClosure(_, _) => None, }, } } @@ -2705,7 +2722,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // desugaring. A closure gets desugared to a struct, and // these extra requirements are basically like where // clauses on the struct. - AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args) => ( + AggregateKind::Closure(def_id, args) + | AggregateKind::CoroutineClosure(def_id, args) + | AggregateKind::Coroutine(def_id, args) => ( def_id, self.prove_closure_bounds( tcx, @@ -2754,10 +2773,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id); let parent_args = match tcx.def_kind(def_id) { - DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => { - args.as_coroutine().parent_args() + DefKind::Closure => { + // FIXME(async_closures): It's kind of icky to access HIR here. + match tcx.hir_node_by_def_id(def_id).expect_closure().kind { + hir::ClosureKind::Closure => args.as_closure().parent_args(), + hir::ClosureKind::Coroutine(_) => args.as_coroutine().parent_args(), + hir::ClosureKind::CoroutineClosure(_) => { + args.as_coroutine_closure().parent_args() + } + } } - DefKind::Closure => args.as_closure().parent_args(), DefKind::InlineConst => args.as_inline_const().parent_args(), other => bug!("unexpected item {:?}", other), }; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index e5c0b2de4ca46..25149b8020162 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -87,7 +87,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout // FIXME(eddyb) producing readable type names for trait objects can result // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | - ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str + ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str if !cx.sess().fewer_names() => { let mut name = with_no_trimmed_paths!(layout.ty.to_string()); diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index e88f4217c9dca..219c702531141 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -33,7 +33,7 @@ fn uncached_llvm_type<'a, 'tcx>( // FIXME(eddyb) producing readable type names for trait objects can result // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | - ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str + ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str // For performance reasons we use names only when emitting LLVM IR. if !cx.sess().fewer_names() => { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 4f9f70648bd88..5bd7442822a21 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -398,7 +398,9 @@ fn push_debuginfo_type_name<'tcx>( // processing visited.remove(&t); } - ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => { + ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) + | ty::Coroutine(def_id, args, ..) => { // Name will be "{closure_env#0}", "{coroutine_env#0}", or // "{async_fn_env#0}", etc. // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of @@ -768,6 +770,8 @@ fn push_closure_or_coroutine_name<'tcx>( // Truncate the args to the length of the above generics. This will cut off // anything closure- or coroutine-specific. + // FIXME(async_closures): This is probably not going to be correct w.r.t. + // multiple coroutine flavors. Maybe truncate to (parent + 1)? let args = args.truncate_to(tcx, generics); push_generic_params_internal(tcx, args, enclosing_fn_def_id, output, visited); } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 12544f5b02955..5c2bf4626c4c3 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -172,6 +172,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>( | ty::Infer(_) // FIXME(oli-obk): we can probably encode closures just like structs | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType), } @@ -301,6 +302,7 @@ pub fn valtree_to_const_value<'tcx>( | ty::Placeholder(..) | ty::Infer(_) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::FnPtr(_) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index c14bd142efacc..dd989ab80fd3c 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1007,6 +1007,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Error(_) => true, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1e9e7d94596f8..7991f90b81549 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -85,6 +85,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index b5cd32595201f..811c2c3c208e0 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -644,6 +644,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' | ty::Str | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) => Ok(false), // Some types only occur during typechecking, they have no layout. // We should not see them here and we could not check them anyway. diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 21bdb66a27631..d3230a2455df3 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -665,6 +665,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; check_equal(self, location, f_ty); } + ty::CoroutineClosure(_, args) => { + let args = args.as_coroutine_closure(); + let Some(&f_ty) = args.upvar_tys().get(f.as_usize()) else { + fail_out_of_bounds(self, location); + return; + }; + check_equal(self, location, f_ty); + } &ty::Coroutine(def_id, args) => { let f_ty = if let Some(var) = parent_ty.variant_index { let gen_body = if def_id == self.body.source.def_id() { @@ -861,6 +869,20 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } } + AggregateKind::CoroutineClosure(_, args) => { + let upvars = args.as_coroutine_closure().upvar_tys(); + if upvars.len() != fields.len() { + self.fail( + location, + "coroutine-closure has the wrong number of initialized fields", + ); + } + for (src, dest) in std::iter::zip(fields, upvars) { + if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) { + self.fail(location, "coroutine-closure field has the wrong type"); + } + } + } }, Rvalue::Ref(_, BorrowKind::Fake, _) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 976e42ad76836..2b80623ab4545 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -51,6 +51,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 539ab5464e961..ff50086ff8f98 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3703,6 +3703,7 @@ impl<'hir> Node<'hir> { expect_generic_param, &'hir GenericParam<'hir>, Node::GenericParam(n), n; expect_crate, &'hir Mod<'hir>, Node::Crate(n), n; expect_infer, &'hir InferArg, Node::Infer(n), n; + expect_closure, &'hir Closure<'hir>, Node::Expr(Expr { kind: ExprKind::Closure(n), .. }), n; } } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index abef365c3ca3c..0df5a57bc2c45 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -171,6 +171,7 @@ impl<'tcx> InherentCollect<'tcx> { } ty::FnDef(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Bound(..) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 1736de760d5a6..45641be52d2f2 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -244,6 +244,7 @@ fn do_orphan_check_impl<'tcx>( | ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther), ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Bound(..) diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index d7e91673c7a29..1dabb6feb5e1b 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -349,7 +349,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { ClosureKind::Coroutine(_) => { &["", "", "", "", ""][..] } - ClosureKind::CoroutineClosure(_) => todo!(), + ClosureKind::CoroutineClosure(_) => &[ + "", + "", + "", + "", + "", + ][..], }; params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef { diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index f09594cbbc667..580cdb4a3a209 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -235,8 +235,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // leaf type -- noop } - ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) => { - bug!("Unexpected closure type in variance computation"); + ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) | ty::CoroutineClosure(..) => { + bug!("Unexpected coroutine/closure type in variance computation"); } ty::Ref(region, ty, mutbl) => { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index b263c98553421..80650dcb53c3f 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check whether this is a call to a closure where we // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. - if self.closure_kind(args).is_none() { + if self.closure_kind(adjusted_ty).is_none() { let closure_sig = args.as_closure().sig(); let closure_sig = self.instantiate_binder_with_fresh_vars( call_expr.span, @@ -160,10 +160,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { DeferredCallResolution { call_expr, callee_expr, - adjusted_ty, + closure_ty: adjusted_ty, adjustments, fn_sig: closure_sig, - closure_args: args, }, ); return Some(CallStep::DeferredClosure(def_id, closure_sig)); @@ -886,10 +885,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub struct DeferredCallResolution<'tcx> { call_expr: &'tcx hir::Expr<'tcx>, callee_expr: &'tcx hir::Expr<'tcx>, - adjusted_ty: Ty<'tcx>, + closure_ty: Ty<'tcx>, adjustments: Vec>, fn_sig: ty::FnSig<'tcx>, - closure_args: GenericArgsRef<'tcx>, } impl<'a, 'tcx> DeferredCallResolution<'tcx> { @@ -898,10 +896,10 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { // we should not be invoked until the closure kind has been // determined by upvar inference - assert!(fcx.closure_kind(self.closure_args).is_some()); + assert!(fcx.closure_kind(self.closure_ty).is_some()); // We may now know enough to figure out fn vs fnmut etc. - match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) { + match fcx.try_overloaded_call_traits(self.call_expr, self.closure_ty, None) { Some((autoref, method_callee)) => { // One problem is that when we get here, we are going // to have a newly instantiated function signature diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index a0ac839f3dd2c..58823ea30ce57 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -133,6 +133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Adt(..) | ty::Never diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 904961d9eba26..2a1c417a16b9c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -57,6 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match ty.kind() { // Not all of these (e.g., unsafe fns) implement `FnOnce`, // so we look for these beforehand. + // FIXME(async_closures): These don't impl `FnOnce` by default. ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true, // If it's not a simple function, look for things which implement `FnOnce`. _ => { diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 864acf51025b5..55ffac8d92f87 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -170,9 +170,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { // Extract the type of the closure. let ty = self.node_ty(closure_hir_id); - let (closure_def_id, args) = match *ty.kind() { - ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args)), - ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args)), + let (closure_def_id, args, infer_kind) = match *ty.kind() { + ty::Closure(def_id, args) => { + (def_id, UpvarArgs::Closure(args), self.closure_kind(ty).is_none()) + } + ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args), false), ty::Error(_) => { // #51714: skip analysis when we have already encountered type errors return; @@ -188,12 +190,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let closure_def_id = closure_def_id.expect_local(); - let infer_kind = if let UpvarArgs::Closure(closure_args) = args { - self.closure_kind(closure_args).is_none().then_some(closure_args) - } else { - None - }; - assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id); let mut delegate = InferBorrowKind { closure_def_id, @@ -308,10 +304,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let before_feature_tys = self.final_upvar_tys(closure_def_id); - if let Some(closure_args) = infer_kind { + if infer_kind { // Unify the (as yet unbound) type variable in the closure // args with the kind we inferred. - let closure_kind_ty = closure_args.as_closure().kind_ty(); + let closure_kind_ty = match args { + UpvarArgs::Closure(args) => args.as_closure().kind_ty(), + UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().kind_ty(), + UpvarArgs::Coroutine(_) => unreachable!("coroutines don't have an inferred kind"), + }; self.demand_eqtype( span, Ty::from_closure_kind(self.tcx, closure_kind), diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index e4b37f05b778f..d825a2920eefb 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -414,6 +414,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Bool diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b8344310d5dfd..cf9d93337839e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2839,7 +2839,11 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { // say, also take a look at the error code, maybe we can // tailor to that. _ => match terr { - TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_coroutine() => Error0644, + TypeError::CyclicTy(ty) + if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() => + { + Error0644 + } TypeError::IntrinsicCast => Error0308, _ => Error0308, }, @@ -2886,7 +2890,9 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { // say, also take a look at the error code, maybe we can // tailor to that. _ => match terr { - TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_coroutine() => { + TypeError::CyclicTy(ty) + if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() => + { ObligationCauseFailureCode::ClosureSelfref { span } } TypeError::IntrinsicCast => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 7287fc26053fe..c637ab31cd214 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -883,7 +883,10 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { GenericArgKind::Type(ty) => { if matches!( ty.kind(), - ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Coroutine(..) + ty::Alias(ty::Opaque, ..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) ) { // Opaque types can't be named by the user right now. // 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 0452d4fe6c806..f884ca83073df 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 @@ -228,7 +228,10 @@ impl Trait for X { #traits-as-parameters", ); } - (ty::Param(p), ty::Closure(..) | ty::Coroutine(..)) => { + ( + ty::Param(p), + ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..), + ) => { let generics = tcx.generics_of(body_owner_def_id); if let Some(param) = generics.opt_type_param(p, tcx) { let p_span = tcx.def_span(param.def_id); @@ -497,7 +500,7 @@ impl Trait for X { } CyclicTy(ty) => { // Watch out for various cases of cyclic types and try to explain. - if ty.is_closure() || ty.is_coroutine() { + if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() { diag.note( "closures cannot capture themselves or take themselves as argument;\n\ this error may be the result of a recent compiler bug-fix,\n\ diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0a39fe007fd22..101735b2961f0 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1538,9 +1538,13 @@ impl<'tcx> InferCtxt<'tcx> { /// Obtains the latest type of the given closure; this may be a /// closure in the current function, in which case its /// `ClosureKind` may not yet be known. - pub fn closure_kind(&self, closure_args: GenericArgsRef<'tcx>) -> Option { - let closure_kind_ty = closure_args.as_closure().kind_ty(); - let closure_kind_ty = self.shallow_resolve(closure_kind_ty); + pub fn closure_kind(&self, closure_ty: Ty<'tcx>) -> Option { + let unresolved_kind_ty = match *closure_ty.kind() { + ty::Closure(_, args) => args.as_closure().kind_ty(), + ty::CoroutineClosure(_, args) => args.as_coroutine_closure().kind_ty(), + _ => bug!("unexpected type {closure_ty}"), + }; + let closure_kind_ty = self.shallow_resolve(unresolved_kind_ty); closure_kind_ty.to_opt_closure_kind() } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index db46b39ce25fc..5ee0a606a5f57 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -456,6 +456,17 @@ where args.as_closure().sig_as_fn_ptr_ty().visit_with(self); } + ty::CoroutineClosure(_, args) => { + // Skip lifetime parameters of the enclosing item(s) + + for upvar in args.as_coroutine_closure().upvar_tys() { + upvar.visit_with(self); + } + + // FIXME(async_closures): Is this the right signature to visit here? + args.as_coroutine_closure().signature_parts_ty().visit_with(self); + } + ty::Coroutine(_, args) => { // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index fc3d8375873b0..7dd1ec3254220 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -103,6 +103,11 @@ fn compute_components<'tcx>( compute_components(tcx, tupled_ty, out, visited); } + ty::CoroutineClosure(_, args) => { + let tupled_ty = args.as_coroutine_closure().tupled_upvars_ty(); + compute_components(tcx, tupled_ty, out, visited); + } + ty::Coroutine(_, args) => { // Same as the closure case let tupled_ty = args.as_coroutine().tupled_upvars_ty(); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index e3d3150b36ef4..1205395b8908d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1435,6 +1435,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { | ty::Bound(..) | ty::Error(_) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Placeholder(..) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index ea3747dfac4b3..9f670893b270d 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -355,7 +355,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { Some(len) => is_ty_must_use(cx, ty, expr, span) .map(|inner| MustUsePath::Array(Box::new(inner), len)), }, - ty::Closure(..) => Some(MustUsePath::Closure(span)), + ty::Closure(..) | ty::CoroutineClosure(..) => Some(MustUsePath::Closure(span)), ty::Coroutine(def_id, ..) => { // async fn should be treated as "implementor of `Future`" let must_use = if cx.tcx.coroutine_is_async(def_id) { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 3b60eba2dfe0a..6f587fdd53c61 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -990,7 +990,8 @@ impl<'tcx> Debug for Rvalue<'tcx> { }) } - AggregateKind::Closure(def_id, args) => ty::tls::with(|tcx| { + AggregateKind::Closure(def_id, args) + | AggregateKind::CoroutineClosure(def_id, args) => ty::tls::with(|tcx| { let name = if tcx.sess.opts.unstable_opts.span_free_formats { let args = tcx.lift(args).unwrap(); format!("{{closure@{}}}", tcx.def_path_str_with_args(def_id, args),) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index a4b6c4f9c3f19..ca56e1fd92c6b 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1350,6 +1350,7 @@ pub enum AggregateKind<'tcx> { Closure(DefId, GenericArgsRef<'tcx>), Coroutine(DefId, GenericArgsRef<'tcx>), + CoroutineClosure(DefId, GenericArgsRef<'tcx>), } #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 5597609c7d796..4780042a51090 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -202,6 +202,9 @@ impl<'tcx> Rvalue<'tcx> { AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args), AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args), AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args), + AggregateKind::CoroutineClosure(did, args) => { + Ty::new_coroutine_closure(tcx, did, args) + } }, Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 4696f54c89787..591104ecc663d 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -739,6 +739,12 @@ macro_rules! make_mir_visitor { ) => { self.visit_args(coroutine_args, location); } + AggregateKind::CoroutineClosure( + _, + coroutine_closure_args, + ) => { + self.visit_args(coroutine_closure_args, location); + } } for operand in operands { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0d53870a0baf0..14d2a93e16714 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1544,6 +1544,7 @@ impl<'tcx> TyCtxt<'tcx> { CoroutineWitness, Dynamic, Closure, + CoroutineClosure, Tuple, Bound, Param, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 0e44878524bf0..80b763d1469e4 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -299,7 +299,7 @@ impl<'tcx> Ty<'tcx> { }, ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(..) => "trait object".into(), - ty::Closure(..) => "closure".into(), + ty::Closure(..) | ty::CoroutineClosure(..) => "closure".into(), ty::Coroutine(def_id, ..) => { format!("{:#}", tcx.coroutine_kind(def_id).unwrap()).into() } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index b71919adc58fa..adc153c4dfd2d 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -128,7 +128,9 @@ pub fn simplify_type<'tcx>( _ => Some(SimplifiedType::MarkerTraitObject), }, ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)), - ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)), + ty::FnDef(def_id, _) | ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _) => { + Some(SimplifiedType::Closure(def_id)) + } ty::Coroutine(def_id, _) => Some(SimplifiedType::Coroutine(def_id)), ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id)), ty::Never => Some(SimplifiedType::Never), @@ -236,6 +238,7 @@ impl DeepRejectCtxt { | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()), ty::FnDef(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Placeholder(..) @@ -312,7 +315,7 @@ impl DeepRejectCtxt { }, // Impls cannot contain these types as these cannot be named directly. - ty::FnDef(..) | ty::Closure(..) | ty::Coroutine(..) => false, + ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) => false, // Placeholder types don't unify with anything on their own ty::Placeholder(..) | ty::Bound(..) => false, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 0c1d10914146f..deb6e73ea7142 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -136,6 +136,22 @@ impl FlagComputation { self.add_ty(args.tupled_upvars_ty()); } + &ty::CoroutineClosure(_, args) => { + let args = args.as_coroutine_closure(); + let should_remove_further_specializable = + !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); + self.add_args(args.parent_args()); + if should_remove_further_specializable { + self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; + } + + self.add_ty(args.signature_parts_ty()); + self.add_ty(args.coroutine_witness_ty()); + self.add_ty(args.coroutine_captures_by_ref_ty()); + self.add_ty(args.kind_ty()); + self.add_ty(args.tupled_upvars_ty()); + } + &ty::Bound(debruijn, _) => { self.add_bound_var(debruijn); self.add_flags(TypeFlags::HAS_TY_BOUND); diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 69ad6810c6fe0..b9fff660a03b9 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -2,7 +2,7 @@ use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; -use crate::ty::sty::{ClosureArgs, CoroutineArgs, InlineConstArgs}; +use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs}; use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; @@ -288,6 +288,14 @@ impl<'tcx> GenericArgs<'tcx> { ClosureArgs { args: self } } + /// Interpret these generic args as the args of a coroutine-closure type. + /// Coroutine-closure args have a particular structure controlled by the + /// compiler that encodes information like the signature and closure kind; + /// see `ty::CoroutineClosureArgs` struct for more comments. + pub fn as_coroutine_closure(&'tcx self) -> CoroutineClosureArgs<'tcx> { + CoroutineClosureArgs { args: self } + } + /// Interpret these generic args as the args of a coroutine type. /// Coroutine args have a particular structure controlled by the /// compiler that encodes information like the signature and coroutine kind; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 73b0e324f13ca..8d8d06b7c0b7f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -906,6 +906,12 @@ where i, ), + ty::CoroutineClosure(_, args) => field_ty_or_layout( + TyAndLayout { ty: args.as_coroutine_closure().tupled_upvars_ty(), ..this }, + cx, + i, + ), + ty::Coroutine(def_id, args) => match this.variants { Variants::Single { index } => TyMaybeWithLayout::Ty( args.as_coroutine() diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index f32b7b0852abc..7026d2af29853 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -259,6 +259,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::FnDef(def_id, _) | ty::Closure(def_id, _) + | ty::CoroutineClosure(def_id, _) | ty::Coroutine(def_id, _) | ty::CoroutineWitness(def_id, _) | ty::Foreign(def_id) => Some(def_id), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index bac5068a69b86..be6b887ba7dc6 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -874,6 +874,48 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } p!("}}"); } + ty::CoroutineClosure(did, args) => { + p!(write("{{")); + if !self.should_print_verbose() { + p!(write("coroutine closure")); + // FIXME(eddyb) should use `def_span`. + if let Some(did) = did.as_local() { + if self.tcx().sess.opts.unstable_opts.span_free_formats { + p!("@", print_def_path(did.to_def_id(), args)); + } else { + let span = self.tcx().def_span(did); + let preference = if with_forced_trimmed_paths() { + FileNameDisplayPreference::Short + } else { + FileNameDisplayPreference::Remapped + }; + p!(write( + "@{}", + // This may end up in stderr diagnostics but it may also be emitted + // into MIR. Hence we use the remapped path if available + self.tcx().sess.source_map().span_to_string(span, preference) + )); + } + } else { + p!(write("@"), print_def_path(did, args)); + } + } else { + p!(print_def_path(did, args)); + p!( + " closure_kind_ty=", + print(args.as_coroutine_closure().kind_ty()), + " signature_parts_ty=", + print(args.as_coroutine_closure().signature_parts_ty()), + " upvar_tys=", + print(args.as_coroutine_closure().tupled_upvars_ty()), + " coroutine_captures_by_ref_ty=", + print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), + " coroutine_witness_ty=", + print(args.as_coroutine_closure().coroutine_witness_ty()) + ); + } + p!("}}"); + } ty::Array(ty, sz) => p!("[", print(ty), "; ", print(sz), "]"), ty::Slice(ty) => p!("[", print(ty), "]"), } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 8543bd0bbdd96..f2321e7e1d22f 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -481,6 +481,13 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(Ty::new_closure(tcx, a_id, args)) } + (&ty::CoroutineClosure(a_id, a_args), &ty::CoroutineClosure(b_id, b_args)) + if a_id == b_id => + { + let args = relate_args_invariantly(relation, a_args, b_args)?; + Ok(Ty::new_coroutine_closure(tcx, a_id, args)) + } + (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; Ok(Ty::new_ptr(tcx, mt)) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 11b579a1f85b6..c6805ba932357 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -584,6 +584,9 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::CoroutineWitness(did, args.try_fold_with(folder)?) } ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?), + ty::CoroutineClosure(did, args) => { + ty::CoroutineClosure(did, args.try_fold_with(folder)?) + } ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), ty::Bool @@ -632,6 +635,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { ty::Coroutine(_did, ref args) => args.visit_with(visitor), ty::CoroutineWitness(_did, ref args) => args.visit_with(visitor), ty::Closure(_did, ref args) => args.visit_with(visitor), + ty::CoroutineClosure(_did, ref args) => args.visit_with(visitor), ty::Alias(_, ref data) => data.visit_with(visitor), ty::Bool diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f5fdf210592e8..c047f6a052151 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -269,6 +269,97 @@ impl<'tcx> ClosureArgs<'tcx> { } } +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] +pub struct CoroutineClosureArgs<'tcx> { + pub args: GenericArgsRef<'tcx>, +} + +pub struct CoroutineClosureArgsParts<'tcx> { + pub parent_args: &'tcx [GenericArg<'tcx>], + pub closure_kind_ty: Ty<'tcx>, + pub signature_parts_ty: Ty<'tcx>, + pub tupled_upvars_ty: Ty<'tcx>, + pub coroutine_captures_by_ref_ty: Ty<'tcx>, + pub coroutine_witness_ty: Ty<'tcx>, +} + +impl<'tcx> CoroutineClosureArgs<'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + parts: CoroutineClosureArgsParts<'tcx>, + ) -> CoroutineClosureArgs<'tcx> { + CoroutineClosureArgs { + args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.closure_kind_ty.into(), + parts.signature_parts_ty.into(), + parts.tupled_upvars_ty.into(), + parts.coroutine_captures_by_ref_ty.into(), + parts.coroutine_witness_ty.into(), + ])), + } + } + + fn split(self) -> CoroutineClosureArgsParts<'tcx> { + match self.args[..] { + [ + ref parent_args @ .., + closure_kind_ty, + signature_parts_ty, + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + coroutine_witness_ty, + ] => CoroutineClosureArgsParts { + parent_args, + closure_kind_ty: closure_kind_ty.expect_ty(), + signature_parts_ty: signature_parts_ty.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(), + coroutine_witness_ty: coroutine_witness_ty.expect_ty(), + }, + _ => bug!("closure args missing synthetics"), + } + } + + pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] { + self.split().parent_args + } + + #[inline] + pub fn upvar_tys(self) -> &'tcx List> { + match self.tupled_upvars_ty().kind() { + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), + TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), + ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), + } + } + + #[inline] + pub fn tupled_upvars_ty(self) -> Ty<'tcx> { + self.split().tupled_upvars_ty + } + + pub fn kind_ty(self) -> Ty<'tcx> { + self.split().closure_kind_ty + } + + pub fn kind(self) -> ty::ClosureKind { + self.kind_ty().to_opt_closure_kind().unwrap() + } + + pub fn signature_parts_ty(self) -> Ty<'tcx> { + self.split().signature_parts_ty + } + + pub fn coroutine_captures_by_ref_ty(self) -> Ty<'tcx> { + self.split().coroutine_captures_by_ref_ty + } + + pub fn coroutine_witness_ty(self) -> Ty<'tcx> { + self.split().coroutine_witness_ty + } +} + /// Similar to `ClosureArgs`; see the above documentation for more. #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] pub struct CoroutineArgs<'tcx> { @@ -479,6 +570,7 @@ impl<'tcx> CoroutineArgs<'tcx> { pub enum UpvarArgs<'tcx> { Closure(GenericArgsRef<'tcx>), Coroutine(GenericArgsRef<'tcx>), + CoroutineClosure(GenericArgsRef<'tcx>), } impl<'tcx> UpvarArgs<'tcx> { @@ -490,6 +582,7 @@ impl<'tcx> UpvarArgs<'tcx> { let tupled_tys = match self { UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(), + UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().tupled_upvars_ty(), }; match tupled_tys.kind() { @@ -505,6 +598,7 @@ impl<'tcx> UpvarArgs<'tcx> { match self { UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(), + UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().tupled_upvars_ty(), } } } @@ -1393,6 +1487,20 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Closure(def_id, closure_args)) } + #[inline] + pub fn new_coroutine_closure( + tcx: TyCtxt<'tcx>, + def_id: DefId, + closure_args: GenericArgsRef<'tcx>, + ) -> Ty<'tcx> { + debug_assert_eq!( + closure_args.len(), + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3, + "closure constructed with incorrect substitutions" + ); + Ty::new(tcx, CoroutineClosure(def_id, closure_args)) + } + #[inline] pub fn new_coroutine( tcx: TyCtxt<'tcx>, @@ -1795,7 +1903,7 @@ impl<'tcx> Ty<'tcx> { type BreakTy = (); fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - if let ty::Closure(_, _) = t.kind() { + if let ty::Closure(..) = t.kind() { ControlFlow::Break(()) } else { t.super_visit_with(self) @@ -1942,6 +2050,7 @@ impl<'tcx> Ty<'tcx> { | ty::FnPtr(..) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) @@ -1980,6 +2089,7 @@ impl<'tcx> Ty<'tcx> { | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Error(_) // Extern types have metadata = (). @@ -2077,6 +2187,7 @@ impl<'tcx> Ty<'tcx> { | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Error(_) => true, @@ -2140,7 +2251,7 @@ impl<'tcx> Ty<'tcx> { ty::Coroutine(..) | ty::CoroutineWitness(..) => false, // Might be, but not "trivial" so just giving the safe answer. - ty::Adt(..) | ty::Closure(..) => false, + ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false, // Needs normalization or revealing to determine, so no is the safe answer. ty::Alias(..) => false, @@ -2212,6 +2323,7 @@ impl<'tcx> Ty<'tcx> { | FnPtr(_) | Dynamic(_, _, _) | Closure(_, _) + | CoroutineClosure(_, _) | Coroutine(_, _) | CoroutineWitness(..) | Never diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8cc8abbe718d1..4feaeb0dd0523 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1119,6 +1119,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(..) | ty::Bound(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Dynamic(..) | ty::Foreign(_) | ty::Coroutine(..) @@ -1158,6 +1159,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(..) | ty::Bound(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Dynamic(..) | ty::Foreign(_) | ty::Coroutine(..) @@ -1280,7 +1282,11 @@ impl<'tcx> Ty<'tcx> { // Conservatively return `false` for all others... // Anonymous function types - ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Coroutine(..) => false, + ty::FnDef(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Dynamic(..) + | ty::Coroutine(..) => false, // Generic or inferred types // @@ -1424,6 +1430,7 @@ pub fn needs_drop_components<'tcx>( | ty::Placeholder(..) | ty::Infer(_) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) => Ok(smallvec![ty]), } @@ -1456,7 +1463,11 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { // Not trivial because they have components, and instead of looking inside, // we'll just perform trait selection. - ty::Closure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Adt(..) => false, + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Adt(..) => false, ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 9050716db9d38..46c26241c3e78 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -189,6 +189,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } ty::Adt(_, args) | ty::Closure(_, args) + | ty::CoroutineClosure(_, args) | ty::Coroutine(_, args) | ty::CoroutineWitness(_, args) | ty::FnDef(_, args) => { diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 6e8af7bb6df6c..c77f4a06d0569 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -483,6 +483,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { UpvarArgs::Closure(args) => { Box::new(AggregateKind::Closure(closure_id.to_def_id(), args)) } + UpvarArgs::CoroutineClosure(args) => { + Box::new(AggregateKind::CoroutineClosure(closure_id.to_def_id(), args)) + } }; block.and(Rvalue::Aggregate(result, operands)) } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 714c5f2686eb5..9bcfe9fbc33e6 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -495,7 +495,7 @@ fn construct_fn<'tcx>( args.as_coroutine().yield_ty(), args.as_coroutine().resume_ty(), ))), - ty::Closure(..) | ty::FnDef(..) => None, + ty::Closure(..) | ty::CoroutineClosure(..) | ty::FnDef(..) => None, ty => span_bug!(span_with_body, "unexpected type of body: {ty:?}"), }; diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 862876f53c76c..1b2f2cd9477fc 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -861,6 +861,9 @@ where let ty = self.place_ty(self.place); match ty.kind() { ty::Closure(_, args) => self.open_drop_for_tuple(args.as_closure().upvar_tys()), + ty::CoroutineClosure(_, args) => { + self.open_drop_for_tuple(args.as_coroutine_closure().upvar_tys()) + } // Note that `elaborate_drops` only drops the upvars of a coroutine, // and this is ok because `open_drop` here can only be reached // within that own coroutine's resume function. diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 38ee26c5a876e..30dd915521cd2 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -154,7 +154,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -177,7 +178,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { union_path.get_or_insert(base); } } - ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (), + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(_, _) + | ty::Tuple(_) => (), ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index dfc7a9891f921..451d3be255fdf 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -39,6 +39,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), ty::Closure(..) => Abi::RustCall, + ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 6c4c3917cb5ec..fbb626953835e 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -128,7 +128,9 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { ), } } - &AggregateKind::Closure(def_id, _) | &AggregateKind::Coroutine(def_id, _) => { + &AggregateKind::Closure(def_id, _) + | &AggregateKind::CoroutineClosure(def_id, _) + | &AggregateKind::Coroutine(def_id, _) => { let def_id = def_id.expect_local(); let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = self.tcx.mir_unsafety_check_result(def_id); diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index ad12bce9b0232..6a37047a69387 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -696,6 +696,7 @@ fn try_write_constant<'tcx>( | ty::Bound(..) | ty::Placeholder(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Dynamic(..) => throw_machine_stop_str!("unsupported type"), diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index db7dfc5b43efa..b0d758bcbfe3b 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -57,6 +57,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), ty::Closure(..) => Abi::RustCall, + ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 390ec3e1a36ac..f9798bc4e70e6 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -861,9 +861,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let tcx = self.tcx; if fields.is_empty() { let is_zst = match *kind { - AggregateKind::Array(..) | AggregateKind::Tuple | AggregateKind::Closure(..) => { - true - } + AggregateKind::Array(..) + | AggregateKind::Tuple + | AggregateKind::Closure(..) + | AggregateKind::CoroutineClosure(..) => true, // Only enums can be non-ZST. AggregateKind::Adt(did, ..) => tcx.def_kind(did) != DefKind::Enum, // Coroutines are never ZST, as they at least contain the implicit states. @@ -885,7 +886,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { assert!(!fields.is_empty()); (AggregateTy::Tuple, FIRST_VARIANT) } - AggregateKind::Closure(did, substs) | AggregateKind::Coroutine(did, substs) => { + AggregateKind::Closure(did, substs) + | AggregateKind::CoroutineClosure(did, substs) + | AggregateKind::Coroutine(did, substs) => { (AggregateTy::Def(did, substs), FIRST_VARIANT) } AggregateKind::Adt(did, variant_index, substs, _, None) => { diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 34d57a45301d7..9a94cae338288 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -46,6 +46,7 @@ fn maybe_zst(ty: Ty<'_>) -> bool { ty::Adt(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Tuple(..) | ty::Alias(ty::Opaque, ..) => true, // definitely ZST diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index db1aee1190359..42edbeaa622c2 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -332,7 +332,8 @@ impl, I: Interner> TypeFolder | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 99f8186d5543b..f7c382bcd7a40 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -719,6 +719,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ty::ClosureKind::FnMut => {} ty::ClosureKind::FnOnce => return succ, }, + ty::CoroutineClosure(_def_id, args) => match args.as_coroutine_closure().kind() { + ty::ClosureKind::Fn => {} + ty::ClosureKind::FnMut => {} + ty::ClosureKind::FnOnce => return succ, + }, ty::Coroutine(..) => return succ, _ => { span_bug!( diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index c02a24048f9bd..b60f32f71c2f1 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -423,7 +423,8 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::Alias(_, _) | ty::Param(_) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a64b06e70d6bc..a37d8822480af 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -182,6 +182,7 @@ where | ty::Foreign(def_id) | ty::FnDef(def_id, ..) | ty::Closure(def_id, ..) + | ty::CoroutineClosure(def_id, ..) | ty::Coroutine(def_id, ..) => { self.def_id_visitor.visit_def_id(def_id, "type", &ty)?; if V::SHALLOW { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index e433460e2ad9d..65ff85a96695b 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -538,6 +538,9 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { tables.tcx.coroutine_movability(*def_id).stable(tables), ) } + mir::AggregateKind::CoroutineClosure(..) => { + todo!("FIXME(async_closure): Lower these to SMIR") + } } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index ba957843bb079..e3fd64eb1891e 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -383,6 +383,7 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { tables.closure_def(*def_id), generic_args.stable(tables), )), + ty::CoroutineClosure(..) => todo!("/* TODO */"), ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine( tables.coroutine_def(*def_id), generic_args.stable(tables), diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 4a5f58443bc29..5af9503087ab9 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -211,6 +211,7 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), // The `pretty_print_type` formatting of array size depends on @@ -281,7 +282,11 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { // Similar to `pretty_path_qualified`, but for the other // types that are printed as paths (see `print_type` above). match self_ty.kind() { - ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Coroutine(..) + ty::FnDef(..) + | ty::Alias(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) if trait_ref.is_none() => { self.print_type(self_ty) diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 0cc82ac7506cb..9d1b92e106803 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -628,7 +628,9 @@ fn encode_ty<'tcx>( } // Function types - ty::FnDef(def_id, args) | ty::Closure(def_id, args) => { + ty::FnDef(def_id, args) + | ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) => { // u[IE], where is , // as vendor extended type. let mut s = String::new(); @@ -895,6 +897,10 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options)); } + ty::CoroutineClosure(def_id, args) => { + ty = Ty::new_coroutine_closure(tcx, *def_id, transform_args(tcx, args, options)); + } + ty::Coroutine(def_id, args) => { ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, options)); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 16ebda55a7a51..d380cb9a19b78 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -386,6 +386,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => { self.print_def_path(def_id, args)?; } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 915d722dd0206..e1c68039e79fb 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -340,7 +340,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::Never | ty::Tuple(_) => { @@ -538,6 +539,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnPtr(_) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never @@ -694,6 +696,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnPtr(_) | ty::Alias(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 274a75a125c58..3c571e1d96f34 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -57,6 +57,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), + ty::CoroutineClosure(_, args) => Ok(vec![args.as_coroutine_closure().tupled_upvars_ty()]), + ty::Coroutine(_, args) => { let coroutine_args = args.as_coroutine(); Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]) @@ -128,6 +130,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Dynamic(_, _, ty::DynStar) | ty::Error(_) => Ok(vec![]), @@ -193,6 +196,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), + ty::CoroutineClosure(..) => Err(NoSolution), + ty::Coroutine(def_id, args) => match ecx.tcx().coroutine_movability(def_id) { Movability::Static => Err(NoSolution), Movability::Movable => { @@ -267,6 +272,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( } Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output())))) } + + // Coroutine closures don't implement `Fn` traits the normal way. + ty::CoroutineClosure(..) => Err(NoSolution), + ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 9f1b4a09a20ba..e1c6f67f05eb0 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -391,6 +391,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) | ty::Coroutine(..) | ty::CoroutineWitness(..) @@ -627,6 +628,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) | ty::Coroutine(..) | ty::CoroutineWitness(..) diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index b185e4e5f8eb0..efaad47b6ddff 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -950,7 +950,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(_) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index c49185a52c7ef..4b20de2621924 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -863,7 +863,7 @@ where } } ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - ty::Closure(did, ..) | ty::Coroutine(did, ..) => { + ty::Closure(did, ..) | ty::CoroutineClosure(did, ..) | ty::Coroutine(did, ..) => { if self.def_id_is_local(did) { ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) } else { 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 d57d9f58333c9..1ac0f172ef4c3 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 @@ -959,9 +959,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligation: &PredicateObligation<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Option { - if let ty::Closure(closure_def_id, closure_args) = *trait_ref.self_ty().skip_binder().kind() + let self_ty = trait_ref.self_ty().skip_binder(); + if let ty::Closure(closure_def_id, closure_args) = *self_ty.kind() && let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) - && let Some(found_kind) = self.closure_kind(closure_args) + && let Some(found_kind) = self.closure_kind(self_ty) && !found_kind.extends(expected_kind) && let sig = closure_args.as_closure().sig() && self.can_sub( @@ -1875,6 +1876,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::Coroutine(..) => Some(18), ty::Foreign(..) => Some(19), ty::CoroutineWitness(..) => Some(20), + ty::CoroutineClosure(..) => Some(21), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index abbc2066eac16..a960befcd4ba8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1854,6 +1854,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::FnPtr(..) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never @@ -1903,6 +1904,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::FnPtr(..) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 79f03242c5876..6c8834f11f1eb 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -48,7 +48,11 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { // (T1..Tn) and closures have same properties as T1..Tn -- // check if *all* of them are trivial. ty::Tuple(tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), + ty::Closure(_, args) => trivial_dropck_outlives(tcx, args.as_closure().tupled_upvars_ty()), + ty::CoroutineClosure(_, args) => { + trivial_dropck_outlives(tcx, args.as_coroutine_closure().tupled_upvars_ty()) + } ty::Adt(def, _) => { if Some(def.did()) == tcx.lang_items().manually_drop() { @@ -239,6 +243,22 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( Ok::<_, NoSolution>(()) })?, + ty::CoroutineClosure(_, args) => { + rustc_data_structures::stack::ensure_sufficient_stack(|| { + for ty in args.as_coroutine_closure().upvar_tys() { + dtorck_constraint_for_ty_inner( + tcx, + param_env, + span, + depth + 1, + ty, + constraints, + )?; + } + Ok::<_, NoSolution>(()) + })? + } + ty::Coroutine(_, args) => { // rust-lang/rust#49918: types can be constructed, stored // in the interior, and sit idle when coroutine yields diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 12aea88e9b6a2..b354ebf111f4c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -306,11 +306,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the args on closure types never // touch bound regions, they just capture the in-scope // type/region parameters - match *obligation.self_ty().skip_binder().kind() { - ty::Closure(def_id, closure_args) => { + let self_ty = obligation.self_ty().skip_binder(); + match *self_ty.kind() { + ty::Closure(def_id, _) => { let is_const = self.tcx().is_const_fn_raw(def_id); debug!(?kind, ?obligation, "assemble_unboxed_candidates"); - match self.infcx.closure_kind(closure_args) { + match self.infcx.closure_kind(self_ty) { Some(closure_kind) => { debug!(?closure_kind, "assemble_unboxed_candidates"); if closure_kind.extends(kind) { @@ -488,7 +489,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -623,7 +625,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(_) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Never | ty::Tuple(_) @@ -1000,6 +1003,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Array(..) | ty::Slice(_) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Tuple(_) | ty::CoroutineWitness(..) => { @@ -1076,7 +1080,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -1139,6 +1144,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Placeholder(..) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6a6adcbb680ea..e79277b89c4ae 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2106,6 +2106,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Dynamic(_, _, ty::DynStar) | ty::Error(_) => { @@ -2227,6 +2228,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } } + // FIXME(async_closures): These are never clone, for now. + ty::CoroutineClosure(_, _) => None, + ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => { // Fallback to whatever user-defined impls exist in this case. None @@ -2305,6 +2309,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { t.rebind(vec![ty]) } + ty::CoroutineClosure(_, args) => { + let ty = self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty()); + t.rebind(vec![ty]) + } + ty::Coroutine(_, args) => { let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); let witness = args.as_coroutine().witness(); diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index d5a37e63d8765..89459f377dd2b 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -79,6 +79,9 @@ impl<'tcx> TypeVisitor> for Search<'tcx> { ty::Closure(..) => { return ControlFlow::Break(ty); } + ty::CoroutineClosure(..) => { + return ControlFlow::Break(ty); + } ty::Coroutine(..) | ty::CoroutineWitness(..) => { return ControlFlow::Break(ty); } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 0f8d9c6bf4bdb..88584a61b13de 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -727,6 +727,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.out.extend(obligations); } + ty::CoroutineClosure(did, args) => { + // See the above comments. + walker.skip_current_subtree(); + self.compute(args.as_coroutine_closure().tupled_upvars_ty().into()); + let obligations = self.nominal_obligations(did, args); + self.out.extend(obligations); + } + ty::FnPtr(_) => { // let the loop iterate into the argument/return // types appearing in the fn signature diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 2d76cf994e437..a5a2c53c7321b 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -215,6 +215,7 @@ fn resolve_associated_item<'tcx>( ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Tuple(..) => {} _ => return Ok(None), }; diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 2fc4bfd4aa31c..f20ded355b1cd 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -328,6 +328,17 @@ fn layout_of_uncached<'tcx>( )? } + ty::CoroutineClosure(_, args) => { + let tys = args.as_coroutine_closure().upvar_tys(); + univariant( + &tys.iter() + .map(|ty| Ok(cx.layout_of(ty)?.layout)) + .try_collect::>()?, + &ReprOptions::default(), + StructKind::AlwaysSized, + )? + } + ty::Tuple(tys) => { let kind = if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 08e5476ae43b7..7b3d2ab22cfa4 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -172,6 +172,12 @@ where } } + ty::CoroutineClosure(_, args) => { + for upvar in args.as_coroutine_closure().upvar_tys() { + queue_type(self, upvar); + } + } + // Check for a `Drop` impl and whether this is a union or // `ManuallyDrop`. If it's a struct or enum without a `Drop` // impl then check whether the field types need `Drop`. diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2158aacab03d8..60b1bbe8c2a5f 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -18,7 +18,9 @@ fn sized_constraint_for_ty<'tcx>( let result = match ty.kind() { Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..) - | FnPtr(_) | Array(..) | Closure(..) | Coroutine(..) | Never => vec![], + | FnPtr(_) | Array(..) | Closure(..) | CoroutineClosure(..) | Coroutine(..) | Never => { + vec![] + } Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | CoroutineWitness(..) => { // these are never sized - return the target type diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 859000fb6cb18..5941fce88250a 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -202,6 +202,9 @@ pub enum TyKind { /// `ClosureArgs` for more details. Closure(I::DefId, I::GenericArgs), + /// TODO + CoroutineClosure(I::DefId, I::GenericArgs), + /// The anonymous type of a coroutine. Used to represent the type of /// `|a| yield a`. /// @@ -317,16 +320,17 @@ const fn tykind_discriminant(value: &TyKind) -> usize { FnPtr(_) => 13, Dynamic(..) => 14, Closure(_, _) => 15, - Coroutine(_, _) => 16, - CoroutineWitness(_, _) => 17, - Never => 18, - Tuple(_) => 19, - Alias(_, _) => 20, - Param(_) => 21, - Bound(_, _) => 22, - Placeholder(_) => 23, - Infer(_) => 24, - Error(_) => 25, + CoroutineClosure(_, _) => 16, + Coroutine(_, _) => 17, + CoroutineWitness(_, _) => 18, + Never => 19, + Tuple(_) => 20, + Alias(_, _) => 21, + Param(_) => 22, + Bound(_, _) => 23, + Placeholder(_) => 24, + Infer(_) => 25, + Error(_) => 26, } } @@ -356,6 +360,7 @@ impl PartialEq for TyKind { a_p == b_p && a_r == b_r && a_repr == b_repr } (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s, + (CoroutineClosure(a_d, a_s), CoroutineClosure(b_d, b_s)) => a_d == b_d && a_s == b_s, (Coroutine(a_d, a_s), Coroutine(b_d, b_s)) => a_d == b_d && a_s == b_s, (CoroutineWitness(a_d, a_s), CoroutineWitness(b_d, b_s)) => a_d == b_d && a_s == b_s, (Tuple(a_t), Tuple(b_t)) => a_t == b_t, @@ -430,6 +435,9 @@ impl DebugWithInfcx for TyKind { } }, Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(), + CoroutineClosure(d, s) => { + f.debug_tuple("CoroutineClosure").field(d).field(&this.wrap(s)).finish() + } Coroutine(d, s) => f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).finish(), CoroutineWitness(d, s) => { f.debug_tuple("CoroutineWitness").field(d).field(&this.wrap(s)).finish() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bd1d68e7074e1..3bac71dbc24e2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2286,6 +2286,7 @@ pub(crate) fn clean_middle_ty<'tcx>( } ty::Closure(..) => panic!("Closure"), + ty::CoroutineClosure(..) => panic!("CoroutineClosure"), ty::Coroutine(..) => panic!("Coroutine"), ty::Placeholder(..) => panic!("Placeholder"), ty::CoroutineWitness(..) => panic!("CoroutineWitness"), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index a75d9bee30490..fe02611b5d449 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -503,6 +503,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } ty::Alias(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Dynamic(..) diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 8ff54dfcfa0dc..194cf69ea7ed0 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -881,6 +881,7 @@ impl TyCoercionStability { | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Tuple(_) | ty::Alias(ty::Projection, _) => Self::Deref, diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index b26ebe5cee321..288df0fd663f0 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -490,6 +490,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { format!("ClosureKind::Coroutine(CoroutineKind::Coroutine(Movability::{movability:?})") }, }, + ClosureKind::CoroutineClosure(desugaring) => format!( + "ClosureKind::CoroutineClosure(CoroutineDesugaring::{desugaring:?})" + ), }; let ret_ty = match fn_decl.output { diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout index 8c4d71e68f80f..579f137f861e1 100644 --- a/src/tools/clippy/tests/ui/author/blocks.stdout +++ b/src/tools/clippy/tests/ui/author/blocks.stdout @@ -40,10 +40,10 @@ if let ExprKind::Block(block, None) = expr.kind { // report your lint here } -if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::Closure, .. } = expr.kind +if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::CoroutineClosure(CoroutineDesugaring::Async), .. } = expr.kind && let FnRetTy::DefaultReturn(_) = fn_decl.output && expr1 = &cx.tcx.hir().body(body_id).value - && let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl1, body: body_id1, closure_kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)), .. } = expr1.kind + && let ExprKind::Closure { capture_clause: CaptureBy::Ref, fn_decl: fn_decl1, body: body_id1, closure_kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)), .. } = expr1.kind && let FnRetTy::DefaultReturn(_) = fn_decl1.output && expr2 = &cx.tcx.hir().body(body_id1).value && let ExprKind::Block(block, None) = expr2.kind diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs index ae7f341fe4e33..cce223c77bbab 100644 --- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs +++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs @@ -29,6 +29,7 @@ fn main() { TyKind::FnPtr(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Dynamic(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Closure(..) => (), //~ ERROR usage of `ty::TyKind::` + TyKind::CoroutineClosure(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Coroutine(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::CoroutineWitness(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Never => (), //~ ERROR usage of `ty::TyKind::` diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr index 45b7c26faad07..2ff5aad95dd87 100644 --- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr +++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr @@ -109,71 +109,77 @@ LL | TyKind::Closure(..) => (), error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:32:9 | -LL | TyKind::Coroutine(..) => (), +LL | TyKind::CoroutineClosure(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:33:9 | -LL | TyKind::CoroutineWitness(..) => (), +LL | TyKind::Coroutine(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:34:9 | -LL | TyKind::Never => (), +LL | TyKind::CoroutineWitness(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:35:9 | -LL | TyKind::Tuple(..) => (), +LL | TyKind::Never => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:36:9 | -LL | TyKind::Alias(..) => (), +LL | TyKind::Tuple(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:37:9 | -LL | TyKind::Param(..) => (), +LL | TyKind::Alias(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:38:9 | -LL | TyKind::Bound(..) => (), +LL | TyKind::Param(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:39:9 | -LL | TyKind::Placeholder(..) => (), +LL | TyKind::Bound(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:40:9 | -LL | TyKind::Infer(..) => (), +LL | TyKind::Placeholder(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:41:9 | +LL | TyKind::Infer(..) => (), + | ^^^^^^ help: try using `ty::` directly: `ty` + +error: usage of `ty::TyKind::` + --> $DIR/ty_tykind_usage.rs:42:9 + | LL | TyKind::Error(_) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:46:12 + --> $DIR/ty_tykind_usage.rs:47:12 | LL | if let TyKind::Int(int_ty) = kind {} | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:48:24 + --> $DIR/ty_tykind_usage.rs:49:24 | LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} | ^^^^^^^^^^ @@ -181,7 +187,7 @@ LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} = help: try using `Ty` instead error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:50:37 + --> $DIR/ty_tykind_usage.rs:51:37 | LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { | ^^^^^^^^^^^ @@ -189,7 +195,7 @@ LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { = help: try using `Ty` instead error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:50:53 + --> $DIR/ty_tykind_usage.rs:51:53 | LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { | ^^^^^^^^^^^ @@ -197,12 +203,12 @@ LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { = help: try using `Ty` instead error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:53:9 + --> $DIR/ty_tykind_usage.rs:54:9 | LL | IrTyKind::Bool | --------^^^^^^ | | | help: try using `ty::` directly: `ty` -error: aborting due to 32 previous errors +error: aborting due to 33 previous errors From a82bae2172499864c12a1d0b412931ad884911f7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jan 2024 22:27:25 +0000 Subject: [PATCH 586/676] Teach typeck/borrowck/solvers how to deal with async closures --- compiler/rustc_ast_lowering/src/expr.rs | 8 + .../src/diagnostics/region_name.rs | 21 +- compiler/rustc_borrowck/src/lib.rs | 1 + .../src/type_check/input_output.rs | 70 ++++++- compiler/rustc_borrowck/src/type_check/mod.rs | 15 +- .../rustc_borrowck/src/universal_regions.rs | 58 +++++- .../src/transform/validate.rs | 1 + compiler/rustc_hir/src/lang_items.rs | 1 + compiler/rustc_hir_analysis/src/collect.rs | 31 +++ compiler/rustc_hir_typeck/src/callee.rs | 85 +++++--- compiler/rustc_hir_typeck/src/closure.rs | 87 ++++++++- compiler/rustc_hir_typeck/src/upvar.rs | 64 +++++- .../rustc_middle/src/middle/lang_items.rs | 15 +- compiler/rustc_middle/src/query/mod.rs | 5 + compiler/rustc_middle/src/traits/select.rs | 7 + compiler/rustc_middle/src/ty/mod.rs | 7 +- compiler/rustc_middle/src/ty/sty.rs | 128 +++++++++++- compiler/rustc_mir_build/src/build/mod.rs | 1 + compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 + compiler/rustc_mir_build/src/thir/cx/mod.rs | 18 +- .../rustc_mir_dataflow/src/value_analysis.rs | 3 + .../src/const_prop_lint.rs | 3 +- .../src/coverage/spans/from_mir.rs | 4 +- compiler/rustc_span/src/symbol.rs | 4 + .../src/solve/assembly/mod.rs | 18 ++ .../src/solve/assembly/structural_traits.rs | 111 ++++++++++- .../src/solve/normalizes_to/mod.rs | 113 +++++++++++ .../src/solve/trait_goals.rs | 60 ++++++ .../src/traits/project.rs | 182 +++++++++++++++++- .../src/traits/select/candidate_assembly.rs | 46 +++++ .../src/traits/select/confirmation.rs | 50 +++++ .../src/traits/select/mod.rs | 12 ++ compiler/rustc_ty_utils/src/abi.rs | 36 ++++ compiler/rustc_ty_utils/src/instance.rs | 11 ++ library/core/src/ops/async_function.rs | 8 + 35 files changed, 1221 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2241b4cd8e504..9990d526bf732 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use super::errors::{ AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters, @@ -1027,6 +1029,12 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); + assert_matches!( + coroutine_kind, + CoroutineKind::Async { .. }, + "only async closures are supported currently" + ); + let body = self.with_new_scopes(fn_decl_span, |this| { let inner_decl = FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index fc52306e10d0b..c91b8eaab055f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -324,9 +324,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty::BoundRegionKind::BrEnv => { let def_ty = self.regioncx.universal_regions().defining_ty; - let DefiningTy::Closure(_, args) = def_ty else { - // Can't have BrEnv in functions, constants or coroutines. - bug!("BrEnv outside of closure."); + let closure_kind = match def_ty { + DefiningTy::Closure(_, args) => args.as_closure().kind(), + DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().kind(), + _ => { + // Can't have BrEnv in functions, constants or coroutines. + bug!("BrEnv outside of closure."); + } }; let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) = tcx.hir().expect_expr(self.mir_hir_id()).kind @@ -334,21 +338,18 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { bug!("Closure is not defined by a closure expr"); }; let region_name = self.synthesize_region_name(); - - let closure_kind_ty = args.as_closure().kind_ty(); - let note = match closure_kind_ty.to_opt_closure_kind() { - Some(ty::ClosureKind::Fn) => { + let note = match closure_kind { + ty::ClosureKind::Fn => { "closure implements `Fn`, so references to captured variables \ can't escape the closure" } - Some(ty::ClosureKind::FnMut) => { + ty::ClosureKind::FnMut => { "closure implements `FnMut`, so references to captured variables \ can't escape the closure" } - Some(ty::ClosureKind::FnOnce) => { + ty::ClosureKind::FnOnce => { bug!("BrEnv in a `FnOnce` closure"); } - None => bug!("Closure kind not inferred in borrow check"), }; Some(RegionName { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index eaf9fc4583720..bb64571889bae 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -3,6 +3,7 @@ #![allow(internal_features)] #![feature(rustdoc_internals)] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(let_chains)] diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 59518f68ab149..a3e5088ee09aa 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,13 +7,18 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). +use std::assert_matches::assert_matches; + use itertools::Itertools; -use rustc_infer::infer::BoundRegionConversionTime; +use rustc_hir as hir; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; -use crate::universal_regions::UniversalRegions; +use crate::renumber::RegionCtxt; +use crate::universal_regions::{DefiningTy, UniversalRegions}; use super::{Locations, TypeChecker}; @@ -23,9 +28,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self, body), level = "debug")] pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) { let mir_def_id = body.source.def_id().expect_local(); + if !self.tcx().is_closure_or_coroutine(mir_def_id.to_def_id()) { return; } + let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id); // Instantiate the canonicalized variables from user-provided signature @@ -34,12 +41,69 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // so that they represent the view from "inside" the closure. let user_provided_sig = self .instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig); - let user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( + let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( body.span, BoundRegionConversionTime::FnCall, user_provided_sig, ); + // FIXME(async_closures): We must apply the same transformation to our + // signature here as we do during closure checking. + if let DefiningTy::CoroutineClosure(_, args) = + self.borrowck_context.universal_regions.defining_ty + { + assert_matches!( + self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)), + Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure + )), + "this needs to be modified if we're lowering non-async closures" + ); + let args = args.as_coroutine_closure(); + let tupled_upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( + self.tcx(), + args.kind(), + Ty::new_tup(self.tcx(), user_provided_sig.inputs()), + args.tupled_upvars_ty(), + args.coroutine_captures_by_ref_ty(), + self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(body.span), || { + RegionCtxt::Unknown + }), + ); + + let next_ty_var = || { + self.infcx.next_ty_var(TypeVariableOrigin { + span: body.span, + kind: TypeVariableOriginKind::MiscVariable, + }) + }; + let output_ty = Ty::new_coroutine( + self.tcx(), + self.tcx().coroutine_for_closure(mir_def_id), + ty::CoroutineArgs::new( + self.tcx(), + ty::CoroutineArgsParts { + parent_args: args.parent_args(), + resume_ty: next_ty_var(), + yield_ty: next_ty_var(), + witness: next_ty_var(), + return_ty: user_provided_sig.output(), + tupled_upvars_ty: tupled_upvars_ty, + }, + ) + .args, + ); + + user_provided_sig = self.tcx().mk_fn_sig( + user_provided_sig.inputs().iter().copied(), + output_ty, + user_provided_sig.c_variadic, + user_provided_sig.unsafety, + user_provided_sig.abi, + ); + } + let is_coroutine_with_implicit_resume_ty = self.tcx().is_coroutine(mir_def_id.to_def_id()) && user_provided_sig.inputs().is_empty(); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 90a9844fda9e4..cdb187e07760a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2773,15 +2773,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id); let parent_args = match tcx.def_kind(def_id) { + // We don't want to dispatch on 3 different kind of closures here, so take + // advantage of the fact that the `parent_args` is the same length as the + // `typeck_root_args`. DefKind::Closure => { - // FIXME(async_closures): It's kind of icky to access HIR here. - match tcx.hir_node_by_def_id(def_id).expect_closure().kind { - hir::ClosureKind::Closure => args.as_closure().parent_args(), - hir::ClosureKind::Coroutine(_) => args.as_coroutine().parent_args(), - hir::ClosureKind::CoroutineClosure(_) => { - args.as_coroutine_closure().parent_args() - } - } + // FIXME(async_closures): It may be useful to add a debug assert here + // to actually call `type_of` and check the `parent_args` are the same + // length as the `typeck_root_args`. + &args[..typeck_root_args.len()] } DefKind::InlineConst => args.as_inline_const().parent_args(), other => bug!("unexpected item {:?}", other), diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index ae8a135f09059..9c266d123b338 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -97,6 +97,10 @@ pub enum DefiningTy<'tcx> { /// `ClosureArgs::coroutine_return_ty`. Coroutine(DefId, GenericArgsRef<'tcx>), + /// The MIR is a special kind of closure that returns coroutines. + /// TODO: describe how to make the sig... + CoroutineClosure(DefId, GenericArgsRef<'tcx>), + /// The MIR is a fn item with the given `DefId` and args. The signature /// of the function can be bound then with the `fn_sig` query. FnDef(DefId, GenericArgsRef<'tcx>), @@ -119,6 +123,7 @@ impl<'tcx> DefiningTy<'tcx> { pub fn upvar_tys(self) -> &'tcx ty::List> { match self { DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), + DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(), DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(), DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { ty::List::empty() @@ -131,7 +136,9 @@ impl<'tcx> DefiningTy<'tcx> { /// user's code. pub fn implicit_inputs(self) -> usize { match self { - DefiningTy::Closure(..) | DefiningTy::Coroutine(..) => 1, + DefiningTy::Closure(..) + | DefiningTy::CoroutineClosure(..) + | DefiningTy::Coroutine(..) => 1, DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0, } } @@ -147,6 +154,7 @@ impl<'tcx> DefiningTy<'tcx> { pub fn def_id(&self) -> DefId { match *self { DefiningTy::Closure(def_id, ..) + | DefiningTy::CoroutineClosure(def_id, ..) | DefiningTy::Coroutine(def_id, ..) | DefiningTy::FnDef(def_id, ..) | DefiningTy::Const(def_id, ..) @@ -355,6 +363,9 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(format!("late-bound region is {:?}", self.to_region_vid(r))); }); } + DefiningTy::CoroutineClosure(..) => { + todo!() + } DefiningTy::Coroutine(def_id, args) => { let v = with_no_trimmed_paths!( args[tcx.generics_of(def_id).parent_count..] @@ -568,6 +579,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { match *defining_ty.kind() { ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args), ty::Coroutine(def_id, args) => DefiningTy::Coroutine(def_id, args), + ty::CoroutineClosure(def_id, args) => { + DefiningTy::CoroutineClosure(def_id, args) + } ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args), _ => span_bug!( tcx.def_span(self.mir_def), @@ -623,6 +637,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); let fr_args = match defining_ty { DefiningTy::Closure(_, args) + | DefiningTy::CoroutineClosure(_, args) | DefiningTy::Coroutine(_, args) | DefiningTy::InlineConst(_, args) => { // In the case of closures, we rely on the fact that @@ -702,6 +717,47 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { ty::Binder::dummy(inputs_and_output) } + DefiningTy::CoroutineClosure(def_id, args) => { + assert_eq!(self.mir_def.to_def_id(), def_id); + let closure_sig = args.as_coroutine_closure().coroutine_closure_sig(); + let bound_vars = tcx.mk_bound_variable_kinds_from_iter( + closure_sig + .bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BrEnv, + }; + let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); + let closure_kind = args.as_coroutine_closure().kind(); + + let closure_ty = tcx.closure_env_ty( + Ty::new_coroutine_closure(tcx, def_id, args), + closure_kind, + env_region, + ); + + let inputs = closure_sig.skip_binder().tupled_inputs_ty.tuple_fields(); + let output = closure_sig.skip_binder().to_coroutine_given_kind_and_upvars( + tcx, + args.as_coroutine_closure().parent_args(), + tcx.coroutine_for_closure(def_id), + closure_kind, + env_region, + args.as_coroutine_closure().tupled_upvars_ty(), + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), + ); + + ty::Binder::bind_with_vars( + tcx.mk_type_list_from_iter( + iter::once(closure_ty).chain(inputs).chain(iter::once(output)), + ), + bound_vars, + ) + } + DefiningTy::FnDef(def_id, _) => { let sig = tcx.fn_sig(def_id).instantiate_identity(); let sig = indices.fold_to_region_vids(tcx, sig); diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index d3230a2455df3..c4542aaa7b2fb 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -58,6 +58,7 @@ impl<'tcx> MirPass<'tcx> for Validator { let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), ty::Closure(..) => Abi::RustCall, + ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, _ => { span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 8e327c029dffc..9c9e72d6e6512 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -209,6 +209,7 @@ language_item_table! { AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1); + AsyncFnKindHelper, sym::async_fn_kind_helper,async_fn_kind_helper, Target::Trait, GenericRequirement::Exact(1); FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8d862d5eb715f..8fdd3cfe3cf88 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -81,6 +81,7 @@ pub fn provide(providers: &mut Providers) { impl_trait_ref, impl_polarity, coroutine_kind, + coroutine_for_closure, collect_mod_item_types, is_type_alias_impl_trait, ..*providers @@ -1531,6 +1532,36 @@ fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option, def_id: LocalDefId) -> DefId { + let Node::Expr(&hir::Expr { + kind: + hir::ExprKind::Closure(&rustc_hir::Closure { + kind: hir::ClosureKind::CoroutineClosure(_), + body, + .. + }), + .. + }) = tcx.hir_node_by_def_id(def_id) + else { + bug!() + }; + + let &hir::Expr { + kind: + hir::ExprKind::Closure(&rustc_hir::Closure { + def_id, + kind: hir::ClosureKind::Coroutine(_), + .. + }), + .. + } = tcx.hir().body(body).value + else { + bug!() + }; + + def_id.to_def_id() +} + fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { match tcx.hir_node_by_def_id(def_id) { Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 80650dcb53c3f..1858b2770cdbc 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -141,32 +141,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Some(CallStep::Builtin(adjusted_ty)); } - ty::Closure(def_id, args) => { + // Check whether this is a call to a closure where we + // haven't yet decided on whether the closure is fn vs + // fnmut vs fnonce. If so, we have to defer further processing. + ty::Closure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { let def_id = def_id.expect_local(); + let closure_sig = args.as_closure().sig(); + let closure_sig = self.instantiate_binder_with_fresh_vars( + call_expr.span, + infer::FnCall, + closure_sig, + ); + let adjustments = self.adjust_steps(autoderef); + self.record_deferred_call_resolution( + def_id, + DeferredCallResolution { + call_expr, + callee_expr, + closure_ty: adjusted_ty, + adjustments, + fn_sig: closure_sig, + }, + ); + return Some(CallStep::DeferredClosure(def_id, closure_sig)); + } - // Check whether this is a call to a closure where we - // haven't yet decided on whether the closure is fn vs - // fnmut vs fnonce. If so, we have to defer further processing. - if self.closure_kind(adjusted_ty).is_none() { - let closure_sig = args.as_closure().sig(); - let closure_sig = self.instantiate_binder_with_fresh_vars( - call_expr.span, - infer::FnCall, - closure_sig, - ); - let adjustments = self.adjust_steps(autoderef); - self.record_deferred_call_resolution( - def_id, - DeferredCallResolution { - call_expr, - callee_expr, - closure_ty: adjusted_ty, - adjustments, - fn_sig: closure_sig, - }, - ); - return Some(CallStep::DeferredClosure(def_id, closure_sig)); - } + ty::CoroutineClosure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { + let def_id = def_id.expect_local(); + let closure_args = args.as_coroutine_closure(); + let coroutine_closure_sig = self.instantiate_binder_with_fresh_vars( + call_expr.span, + infer::FnCall, + closure_args.coroutine_closure_sig(), + ); + let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: callee_expr.span, + }); + let call_sig = self.tcx.mk_fn_sig( + [coroutine_closure_sig.tupled_inputs_ty], + coroutine_closure_sig.to_coroutine( + self.tcx, + closure_args.parent_args(), + self.tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ), + coroutine_closure_sig.c_variadic, + coroutine_closure_sig.unsafety, + coroutine_closure_sig.abi, + ); + let adjustments = self.adjust_steps(autoderef); + self.record_deferred_call_resolution( + def_id, + DeferredCallResolution { + call_expr, + callee_expr, + closure_ty: adjusted_ty, + adjustments, + fn_sig: call_sig, + }, + ); + return Some(CallStep::DeferredClosure(def_id, call_sig)); } // Hack: we know that there are traits implementing Fn for &F @@ -935,7 +970,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { span_bug!( self.call_expr.span, "Expected to find a suitable `Fn`/`FnMut`/`FnOnce` implementation for `{}`", - self.adjusted_ty + self.closure_ty ) } } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 18dff5188af94..1d024efdd499f 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -63,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => (None, None), }; - let ClosureSignatures { bound_sig, liberated_sig } = + let ClosureSignatures { bound_sig, mut liberated_sig } = self.sig_of_closure(expr_def_id, closure.fn_decl, closure.kind, expected_sig); debug!(?bound_sig, ?liberated_sig); @@ -125,7 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) | hir::CoroutineKind::Coroutine(_) => { let yield_ty = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, + kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, }); self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType); @@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // not a problem. hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => { let yield_ty = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, + kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, }); self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType); @@ -166,8 +166,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); let interior = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: body.value.span, + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, }); self.deferred_coroutine_interiors.borrow_mut().push(( expr_def_id, @@ -192,7 +192,82 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(CoroutineTypes { resume_ty, yield_ty }), ) } - hir::ClosureKind::CoroutineClosure(_) => todo!(), + hir::ClosureKind::CoroutineClosure(kind) => { + let (bound_return_ty, bound_yield_ty) = match kind { + hir::CoroutineDesugaring::Async => { + (bound_sig.skip_binder().output(), tcx.types.unit) + } + hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen => { + todo!("`gen` and `async gen` closures not supported yet") + } + }; + let resume_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + let interior = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + let closure_kind_ty = self.next_ty_var(TypeVariableOrigin { + // FIXME(eddyb) distinguish closure kind inference variables from the rest. + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + let coroutine_captures_by_ref_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + let closure_args = ty::CoroutineClosureArgs::new( + tcx, + ty::CoroutineClosureArgsParts { + parent_args, + closure_kind_ty, + signature_parts_ty: Ty::new_fn_ptr( + tcx, + bound_sig.map_bound(|sig| { + tcx.mk_fn_sig( + [ + resume_ty, + Ty::new_tup_from_iter(tcx, sig.inputs().iter().copied()), + ], + Ty::new_tup(tcx, &[bound_yield_ty, bound_return_ty]), + sig.c_variadic, + sig.unsafety, + sig.abi, + ) + }), + ), + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + coroutine_witness_ty: interior, + }, + ); + + let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + liberated_sig = tcx.mk_fn_sig( + liberated_sig.inputs().iter().copied(), + tcx.liberate_late_bound_regions( + expr_def_id.to_def_id(), + closure_args.coroutine_closure_sig().map_bound(|sig| { + sig.to_coroutine( + tcx, + parent_args, + tcx.coroutine_for_closure(expr_def_id), + coroutine_upvars_ty, + ) + }), + ), + liberated_sig.c_variadic, + liberated_sig.unsafety, + liberated_sig.abi, + ); + + (Ty::new_coroutine_closure(tcx, expr_def_id.to_def_id(), closure_args.args), None) + } }; check_fn( diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 55ffac8d92f87..b087d6d9e570d 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -174,6 +174,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Closure(def_id, args) => { (def_id, UpvarArgs::Closure(args), self.closure_kind(ty).is_none()) } + ty::CoroutineClosure(def_id, args) => { + (def_id, UpvarArgs::CoroutineClosure(args), self.closure_kind(ty).is_none()) + } ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args), false), ty::Error(_) => { // #51714: skip analysis when we have already encountered type errors @@ -333,6 +336,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + if let UpvarArgs::CoroutineClosure(args) = args { + let closure_env_region: ty::Region<'_> = ty::Region::new_bound( + self.tcx, + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(0), + kind: ty::BoundRegionKind::BrEnv, + }, + ); + let tupled_upvars_ty_for_borrow = Ty::new_tup_from_iter( + self.tcx, + self.typeck_results + .borrow() + .closure_min_captures_flattened( + self.tcx.coroutine_for_closure(closure_def_id).expect_local(), + ) + // Skip the captures that are just moving the closure's args + // into the coroutine. These are always by move. + .skip( + args.as_coroutine_closure() + .coroutine_closure_sig() + .skip_binder() + .tupled_inputs_ty + .tuple_fields() + .len(), + ) + .map(|captured_place| { + let upvar_ty = captured_place.place.ty(); + let capture = captured_place.info.capture_kind; + apply_capture_kind_on_capture_ty( + self.tcx, + upvar_ty, + capture, + Some(closure_env_region), + ) + }), + ); + let coroutine_captures_by_ref_ty = Ty::new_fn_ptr( + self.tcx, + ty::Binder::bind_with_vars( + self.tcx.mk_fn_sig( + [], + tupled_upvars_ty_for_borrow, + false, + hir::Unsafety::Normal, + rustc_target::spec::abi::Abi::Rust, + ), + self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region( + ty::BoundRegionKind::BrEnv, + )]), + ), + ); + self.demand_eqtype( + span, + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), + coroutine_captures_by_ref_ty, + ); + } + self.log_closure_min_capture_info(closure_def_id, span); // Now that we've analyzed the closure, we know how each @@ -602,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Go through each entry in the current list of min_captures - // - if ancestor is found, update it's capture kind to account for current place's + // - if ancestor is found, update its capture kind to account for current place's // capture information. // // - if descendant is found, remove it from the list, and update the current place's diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index f92c72c8a588c..a4e193ba2c942 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -23,7 +23,7 @@ impl<'tcx> TyCtxt<'tcx> { }) } - /// Given a [`DefId`] of a [`Fn`], [`FnMut`] or [`FnOnce`] traits, + /// Given a [`DefId`] of one of the [`Fn`], [`FnMut`] or [`FnOnce`] traits, /// returns a corresponding [`ty::ClosureKind`]. /// For any other [`DefId`] return `None`. pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option { @@ -36,6 +36,19 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Given a [`DefId`] of one of the `AsyncFn`, `AsyncFnMut` or `AsyncFnOnce` traits, + /// returns a corresponding [`ty::ClosureKind`]. + /// For any other [`DefId`] return `None`. + pub fn async_fn_trait_kind_from_def_id(self, id: DefId) -> Option { + let items = self.lang_items(); + match Some(id) { + x if x == items.async_fn_trait() => Some(ty::ClosureKind::Fn), + x if x == items.async_fn_mut_trait() => Some(ty::ClosureKind::FnMut), + x if x == items.async_fn_once_trait() => Some(ty::ClosureKind::FnOnce), + _ => None, + } + } + /// Given a [`ty::ClosureKind`], get the [`DefId`] of its corresponding `Fn`-family /// trait, if it is defined. pub fn fn_trait_kind_to_def_id(self, kind: ty::ClosureKind) -> Option { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2438f826441d2..f9ab32b16f534 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -755,6 +755,11 @@ rustc_queries! { separate_provide_extern } + query coroutine_for_closure(def_id: DefId) -> DefId { + desc { |_tcx| "TODO" } + separate_provide_extern + } + /// Gets a map with the variance of every item; use `variances_of` instead. query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> { arena_cache diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 64f4af08e12ed..4e11575cf9800 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -134,6 +134,13 @@ pub enum SelectionCandidate<'tcx> { is_const: bool, }, + /// Implementation of an `AsyncFn`-family trait by one of the anonymous types + /// generated for an `async ||` expression. + AsyncClosureCandidate, + + // TODO: + AsyncFnKindHelperCandidate, + /// Implementation of a `Coroutine` trait by one of the anonymous types /// generated for a coroutine. CoroutineCandidate, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8e51db82f95ae..4348d01eff58c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -105,9 +105,10 @@ pub use self::region::{ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, - ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, FnSig, GenSig, - InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, - UpvarArgs, VarianceDiagInfo, + ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs, + CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs, + InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, + VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c047f6a052151..e2a2e24f06dd8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -36,6 +36,7 @@ use rustc_type_ir::TyKind as IrTyKind; use rustc_type_ir::TyKind::*; use rustc_type_ir::TypeAndMut as IrTypeAndMut; +use super::fold::FnMutDelegate; use super::GenericParamDefKind; // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here @@ -351,6 +352,27 @@ impl<'tcx> CoroutineClosureArgs<'tcx> { self.split().signature_parts_ty } + pub fn coroutine_closure_sig(self) -> ty::Binder<'tcx, CoroutineClosureSignature<'tcx>> { + let interior = self.coroutine_witness_ty(); + let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { bug!() }; + sig.map_bound(|sig| { + let [resume_ty, tupled_inputs_ty] = *sig.inputs() else { + bug!(); + }; + let [yield_ty, return_ty] = **sig.output().tuple_fields() else { bug!() }; + CoroutineClosureSignature { + interior, + tupled_inputs_ty, + resume_ty, + yield_ty, + return_ty, + c_variadic: sig.c_variadic, + unsafety: sig.unsafety, + abi: sig.abi, + } + }) + } + pub fn coroutine_captures_by_ref_ty(self) -> Ty<'tcx> { self.split().coroutine_captures_by_ref_ty } @@ -360,6 +382,103 @@ impl<'tcx> CoroutineClosureArgs<'tcx> { } } +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] +pub struct CoroutineClosureSignature<'tcx> { + pub interior: Ty<'tcx>, + pub tupled_inputs_ty: Ty<'tcx>, + pub resume_ty: Ty<'tcx>, + pub yield_ty: Ty<'tcx>, + pub return_ty: Ty<'tcx>, + pub c_variadic: bool, + pub unsafety: hir::Unsafety, + pub abi: abi::Abi, +} + +impl<'tcx> CoroutineClosureSignature<'tcx> { + pub fn to_coroutine( + self, + tcx: TyCtxt<'tcx>, + parent_args: &'tcx [GenericArg<'tcx>], + coroutine_def_id: DefId, + tupled_upvars_ty: Ty<'tcx>, + ) -> Ty<'tcx> { + let coroutine_args = ty::CoroutineArgs::new( + tcx, + ty::CoroutineArgsParts { + parent_args, + resume_ty: self.resume_ty, + yield_ty: self.yield_ty, + return_ty: self.return_ty, + witness: self.interior, + tupled_upvars_ty, + }, + ); + + Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args) + } + + pub fn to_coroutine_given_kind_and_upvars( + self, + tcx: TyCtxt<'tcx>, + parent_args: &'tcx [GenericArg<'tcx>], + coroutine_def_id: DefId, + closure_kind: ty::ClosureKind, + env_region: ty::Region<'tcx>, + closure_tupled_upvars_ty: Ty<'tcx>, + coroutine_captures_by_ref_ty: Ty<'tcx>, + ) -> Ty<'tcx> { + let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind( + tcx, + closure_kind, + self.tupled_inputs_ty, + closure_tupled_upvars_ty, + coroutine_captures_by_ref_ty, + env_region, + ); + + self.to_coroutine(tcx, parent_args, coroutine_def_id, tupled_upvars_ty) + } + + /// Given a closure kind, compute the tupled upvars that the given coroutine would return. + pub fn tupled_upvars_by_closure_kind( + tcx: TyCtxt<'tcx>, + kind: ty::ClosureKind, + tupled_inputs_ty: Ty<'tcx>, + closure_tupled_upvars_ty: Ty<'tcx>, + coroutine_captures_by_ref_ty: Ty<'tcx>, + env_region: ty::Region<'tcx>, + ) -> Ty<'tcx> { + match kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { + let ty::FnPtr(sig) = *coroutine_captures_by_ref_ty.kind() else { + bug!(); + }; + let coroutine_captures_by_ref_ty = tcx.replace_escaping_bound_vars_uncached( + sig.output().skip_binder(), + FnMutDelegate { + consts: &mut |c, t| ty::Const::new_bound(tcx, ty::INNERMOST, c, t), + types: &mut |t| Ty::new_bound(tcx, ty::INNERMOST, t), + regions: &mut |_| env_region, + }, + ); + Ty::new_tup_from_iter( + tcx, + tupled_inputs_ty + .tuple_fields() + .iter() + .chain(coroutine_captures_by_ref_ty.tuple_fields()), + ) + } + ty::ClosureKind::FnOnce => Ty::new_tup_from_iter( + tcx, + tupled_inputs_ty + .tuple_fields() + .iter() + .chain(closure_tupled_upvars_ty.tuple_fields()), + ), + } + } +} /// Similar to `ClosureArgs`; see the above documentation for more. #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] pub struct CoroutineArgs<'tcx> { @@ -1495,7 +1614,7 @@ impl<'tcx> Ty<'tcx> { ) -> Ty<'tcx> { debug_assert_eq!( closure_args.len(), - tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3, + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, "closure constructed with incorrect substitutions" ); Ty::new(tcx, CoroutineClosure(def_id, closure_args)) @@ -1835,6 +1954,11 @@ impl<'tcx> Ty<'tcx> { matches!(self.kind(), Coroutine(..)) } + #[inline] + pub fn is_coroutine_closure(self) -> bool { + matches!(self.kind(), CoroutineClosure(..)) + } + #[inline] pub fn is_integral(self) -> bool { matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_)) @@ -2144,7 +2268,7 @@ impl<'tcx> Ty<'tcx> { // "Bound" types appear in canonical queries when the // closure type is not yet known - Bound(..) | Infer(_) => None, + Bound(..) | Param(_) | Infer(_) => None, Error(_) => Some(ty::ClosureKind::Fn), diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 9bcfe9fbc33e6..9a2f2ceced1ed 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -822,6 +822,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let upvar_args = match closure_ty.kind() { ty::Closure(_, args) => ty::UpvarArgs::Closure(args), ty::Coroutine(_, args) => ty::UpvarArgs::Coroutine(args), + ty::CoroutineClosure(_, args) => ty::UpvarArgs::CoroutineClosure(args), _ => return, }; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 22094c112fc18..35adcc33480ca 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -556,6 +556,9 @@ impl<'tcx> Cx<'tcx> { ty::Coroutine(def_id, args) => { (def_id, UpvarArgs::Coroutine(args), Some(tcx.coroutine_movability(def_id))) } + ty::CoroutineClosure(def_id, args) => { + (def_id, UpvarArgs::CoroutineClosure(args), None) + } _ => { span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 5d0bb3954ccc6..f4f591d15b933 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -127,10 +127,24 @@ impl<'tcx> Cx<'tcx> { ty::Coroutine(..) => { Param { ty: closure_ty, pat: None, ty_span: None, self_kind: None, hir_id: None } } - ty::Closure(_, closure_args) => { + ty::Closure(_, args) => { let closure_env_ty = self.tcx.closure_env_ty( closure_ty, - closure_args.as_closure().kind(), + args.as_closure().kind(), + self.tcx.lifetimes.re_erased, + ); + Param { + ty: closure_env_ty, + pat: None, + ty_span: None, + self_kind: None, + hir_id: None, + } + } + ty::CoroutineClosure(_, args) => { + let closure_env_ty = self.tcx.closure_env_ty( + closure_ty, + args.as_coroutine_closure().kind(), self.tcx.lifetimes.re_erased, ); Param { diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 2802f5491be03..a85e53ff241d5 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -1149,6 +1149,9 @@ pub fn iter_fields<'tcx>( ty::Closure(_, args) => { iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f); } + ty::CoroutineClosure(_, args) => { + iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, param_env, f); + } _ => (), } } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index aa22b8c7c58e0..f2448ee3d44af 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -607,7 +607,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { AggregateKind::Array(_) | AggregateKind::Tuple | AggregateKind::Closure(_, _) - | AggregateKind::Coroutine(_, _) => VariantIdx::new(0), + | AggregateKind::Coroutine(_, _) + | AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0), }, }, 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 5b4d58836b486..01fae7c0bec86 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -156,7 +156,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( fn is_closure_or_coroutine(statement: &Statement<'_>) -> bool { match statement.kind { StatementKind::Assign(box (_, Rvalue::Aggregate(box ref agg_kind, _))) => match agg_kind { - AggregateKind::Closure(_, _) | AggregateKind::Coroutine(_, _) => true, + AggregateKind::Closure(_, _) + | AggregateKind::Coroutine(_, _) + | AggregateKind::CoroutineClosure(..) => true, _ => false, }, _ => false, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index dbfc89c2d496e..587eb1c7cc5ae 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -167,6 +167,9 @@ symbols! { Break, C, CStr, + CallFuture, + CallMutFuture, + CallOnceFuture, Capture, Center, Cleanup, @@ -420,6 +423,7 @@ symbols! { async_closure, async_fn, async_fn_in_trait, + async_fn_kind_helper, async_fn_mut, async_fn_once, async_fn_track_caller, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index e1c68039e79fb..8451fbcc434cd 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -182,6 +182,20 @@ pub(super) trait GoalKind<'tcx>: kind: ty::ClosureKind, ) -> QueryResult<'tcx>; + /// An async closure is known to implement the `AsyncFn` family of traits + /// where `A` is given by the signature of the type. + fn consider_builtin_async_fn_trait_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + kind: ty::ClosureKind, + ) -> QueryResult<'tcx>; + + /// TODO: + fn consider_builtin_async_fn_kind_helper_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx>; + /// `Tuple` is implemented if the `Self` type is a tuple. fn consider_builtin_tuple_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, @@ -461,6 +475,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_fn_ptr_trait_candidate(self, goal) } else if let Some(kind) = self.tcx().fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_fn_trait_candidates(self, goal, kind) + } else if let Some(kind) = self.tcx().async_fn_trait_kind_from_def_id(trait_def_id) { + G::consider_builtin_async_fn_trait_candidates(self, goal, kind) + } else if lang_items.async_fn_kind_helper() == Some(trait_def_id) { + G::consider_builtin_async_fn_kind_helper_candidate(self, goal) } else if lang_items.tuple_trait() == Some(trait_def_id) { G::consider_builtin_tuple_candidate(self, goal) } else if lang_items.pointee_trait() == Some(trait_def_id) { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 3c571e1d96f34..c35134c78eb16 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -1,11 +1,12 @@ //! Code which is used by built-in goals that match "structurally", such a auto //! traits, `Copy`/`Clone`. use rustc_data_structures::fx::FxHashMap; +use rustc_hir::LangItem; use rustc_hir::{def_id::DefId, Movability, Mutability}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use crate::solve::EvalCtxt; @@ -306,6 +307,114 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( } } +// Returns a binder of the tupled inputs types, output type, and coroutine type +// from a builtin async closure type. +pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tcx>( + tcx: TyCtxt<'tcx>, + self_ty: Ty<'tcx>, + goal_kind: ty::ClosureKind, + env_region: ty::Region<'tcx>, +) -> Result<(ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Vec>), NoSolution> +{ + match *self_ty.kind() { + ty::CoroutineClosure(def_id, args) => { + let args = args.as_coroutine_closure(); + let kind_ty = args.kind_ty(); + + if let Some(closure_kind) = kind_ty.to_opt_closure_kind() { + if !closure_kind.extends(goal_kind) { + return Err(NoSolution); + } + Ok(( + args.coroutine_closure_sig().map_bound(|sig| { + let coroutine_ty = sig.to_coroutine_given_kind_and_upvars( + tcx, + args.parent_args(), + tcx.coroutine_for_closure(def_id), + goal_kind, + env_region, + args.tupled_upvars_ty(), + args.coroutine_captures_by_ref_ty(), + ); + (sig.tupled_inputs_ty, sig.return_ty, coroutine_ty) + }), + vec![], + )) + } else { + let helper_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); + // FIXME(async_closures): Make this into a lang item. + let upvars_projection_def_id = tcx + .associated_items(helper_trait_def_id) + .in_definition_order() + .next() + .unwrap() + .def_id; + Ok(( + args.coroutine_closure_sig().map_bound(|sig| { + let tupled_upvars_ty = Ty::new_projection( + tcx, + upvars_projection_def_id, + [ + ty::GenericArg::from(kind_ty), + Ty::from_closure_kind(tcx, goal_kind).into(), + env_region.into(), + sig.tupled_inputs_ty.into(), + args.tupled_upvars_ty().into(), + args.coroutine_captures_by_ref_ty().into(), + ], + ); + let coroutine_ty = sig.to_coroutine( + tcx, + args.parent_args(), + tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ); + (sig.tupled_inputs_ty, sig.return_ty, coroutine_ty) + }), + vec![ + ty::TraitRef::new( + tcx, + helper_trait_def_id, + [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], + ) + .to_predicate(tcx), + ], + )) + } + } + + ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) => Err(NoSolution), + + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::Dynamic(_, _, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Tuple(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Placeholder(..) + | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) + | ty::Error(_) => Err(NoSolution), + + ty::Bound(..) + | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + bug!("unexpected type `{self_ty}`") + } + } +} + /// Assemble a list of predicates that would be present on a theoretical /// user impl for an object type. These predicates must be checked any time /// we assemble a built-in object candidate for an object type, since they diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index e1c6f67f05eb0..47ba549022d9b 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -366,6 +366,119 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)]) } + fn consider_builtin_async_fn_trait_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + goal_kind: ty::ClosureKind, + ) -> QueryResult<'tcx> { + let tcx = ecx.tcx(); + + let env_region = match goal_kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2), + // Doesn't matter what this region is + ty::ClosureKind::FnOnce => tcx.lifetimes.re_static, + }; + let (tupled_inputs_and_output_and_coroutine, nested_preds) = + structural_traits::extract_tupled_inputs_and_output_from_async_callable( + tcx, + goal.predicate.self_ty(), + goal_kind, + env_region, + )?; + let output_is_sized_pred = + tupled_inputs_and_output_and_coroutine.map_bound(|(_, output, _)| { + ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output]) + }); + + let pred = tupled_inputs_and_output_and_coroutine + .map_bound(|(inputs, output, coroutine)| { + let (projection_ty, term) = match tcx.item_name(goal.predicate.def_id()) { + sym::CallOnceFuture => ( + ty::AliasTy::new( + tcx, + goal.predicate.def_id(), + [goal.predicate.self_ty(), inputs], + ), + coroutine.into(), + ), + sym::CallMutFuture | sym::CallFuture => ( + ty::AliasTy::new( + tcx, + goal.predicate.def_id(), + [ + ty::GenericArg::from(goal.predicate.self_ty()), + inputs.into(), + env_region.into(), + ], + ), + coroutine.into(), + ), + sym::Output => ( + ty::AliasTy::new( + tcx, + goal.predicate.def_id(), + [ty::GenericArg::from(goal.predicate.self_ty()), inputs.into()], + ), + output.into(), + ), + name => bug!("no such associated type: {name}"), + }; + ty::ProjectionPredicate { projection_ty, term } + }) + .to_predicate(tcx); + + // A built-in `AsyncFn` impl only holds if the output is sized. + // (FIXME: technically we only need to check this if the type is a fn ptr...) + Self::consider_implied_clause( + ecx, + goal, + pred, + [goal.with(tcx, output_is_sized_pred)] + .into_iter() + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + ) + } + + fn consider_builtin_async_fn_kind_helper_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let [ + closure_fn_kind_ty, + goal_kind_ty, + borrow_region, + tupled_inputs_ty, + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + ] = **goal.predicate.alias.args + else { + bug!(); + }; + + let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else { + // We don't need to worry about the self type being an infer var. + return Err(NoSolution); + }; + let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else { + return Err(NoSolution); + }; + if !closure_kind.extends(goal_kind) { + return Err(NoSolution); + } + + let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( + ecx.tcx(), + goal_kind, + tupled_inputs_ty.expect_ty(), + tupled_upvars_ty.expect_ty(), + coroutine_captures_by_ref_ty.expect_ty(), + borrow_region.expect_region(), + ); + + ecx.eq(goal.param_env, goal.predicate.term.ty().unwrap(), upvars_ty)?; + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + fn consider_builtin_tuple_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index efaad47b6ddff..fd09a6b671dad 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -303,6 +303,66 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)]) } + fn consider_builtin_async_fn_trait_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + goal_kind: ty::ClosureKind, + ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + + let tcx = ecx.tcx(); + let (tupled_inputs_and_output_and_coroutine, nested_preds) = + structural_traits::extract_tupled_inputs_and_output_from_async_callable( + tcx, + goal.predicate.self_ty(), + goal_kind, + // This region doesn't matter because we're throwing away the coroutine type + tcx.lifetimes.re_static, + )?; + let output_is_sized_pred = + tupled_inputs_and_output_and_coroutine.map_bound(|(_, output, _)| { + ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output]) + }); + + let pred = tupled_inputs_and_output_and_coroutine + .map_bound(|(inputs, _, _)| { + ty::TraitRef::new(tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]) + }) + .to_predicate(tcx); + // A built-in `AsyncFn` impl only holds if the output is sized. + // (FIXME: technically we only need to check this if the type is a fn ptr...) + Self::consider_implied_clause( + ecx, + goal, + pred, + [goal.with(tcx, output_is_sized_pred)] + .into_iter() + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + ) + } + + fn consider_builtin_async_fn_kind_helper_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else { + bug!(); + }; + + let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else { + // We don't need to worry about the self type being an infer var. + return Err(NoSolution); + }; + let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap(); + if closure_kind.extends(goal_kind) { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } else { + Err(NoSolution) + } + } + fn consider_builtin_tuple_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index a960befcd4ba8..648f14beaa7a3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1833,10 +1833,28 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( lang_items.fn_trait(), lang_items.fn_mut_trait(), lang_items.fn_once_trait(), + lang_items.async_fn_trait(), + lang_items.async_fn_mut_trait(), + lang_items.async_fn_once_trait(), ].contains(&Some(trait_ref.def_id)) { true - }else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) { + } else if lang_items.async_fn_kind_helper() == Some(trait_ref.def_id) { + // FIXME(async_closures): Validity constraints here could be cleaned up. + if obligation.predicate.args.type_at(0).is_ty_var() + || obligation.predicate.args.type_at(4).is_ty_var() + || obligation.predicate.args.type_at(5).is_ty_var() + { + candidate_set.mark_ambiguous(); + true + } else if obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some() + && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some() + { + true + } else { + false + } + } else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) { match self_ty.kind() { ty::Bool | ty::Char @@ -2061,6 +2079,10 @@ fn confirm_select_candidate<'cx, 'tcx>( } else { confirm_fn_pointer_candidate(selcx, obligation, data) } + } else if selcx.tcx().async_fn_trait_kind_from_def_id(trait_def_id).is_some() { + confirm_async_closure_candidate(selcx, obligation, data) + } else if lang_items.async_fn_kind_helper() == Some(trait_def_id) { + confirm_async_fn_kind_helper_candidate(selcx, obligation, data) } else { confirm_builtin_candidate(selcx, obligation, data) } @@ -2421,6 +2443,164 @@ fn confirm_callable_candidate<'cx, 'tcx>( confirm_param_env_candidate(selcx, obligation, predicate, true) } +fn confirm_async_closure_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + mut nested: Vec>, +) -> Progress<'tcx> { + let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); + let ty::CoroutineClosure(def_id, args) = *self_ty.kind() else { + unreachable!( + "expected coroutine-closure self type for coroutine-closure candidate, found {self_ty}" + ) + }; + let args = args.as_coroutine_closure(); + let kind_ty = args.kind_ty(); + + let tcx = selcx.tcx(); + let goal_kind = + tcx.async_fn_trait_kind_from_def_id(obligation.predicate.trait_def_id(tcx)).unwrap(); + + let helper_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); + nested.push(obligation.with( + tcx, + ty::TraitRef::new( + tcx, + helper_trait_def_id, + [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], + ), + )); + + let env_region = match goal_kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => obligation.predicate.args.region_at(2), + ty::ClosureKind::FnOnce => tcx.lifetimes.re_static, + }; + + // FIXME(async_closures): Make this into a lang item. + let upvars_projection_def_id = + tcx.associated_items(helper_trait_def_id).in_definition_order().next().unwrap().def_id; + + // FIXME(async_closures): Confirmation is kind of a mess here. Ideally, + // we'd short-circuit when we know that the goal_kind >= closure_kind, and not + // register a nested predicate or create a new projection ty here. But I'm too + // lazy to make this more efficient atm, and we can always tweak it later, + // since all this does is make the solver do more work. + // + // The code duplication due to the different length args is kind of weird, too. + let poly_cache_entry = args.coroutine_closure_sig().map_bound(|sig| { + let (projection_ty, term) = match tcx.item_name(obligation.predicate.def_id) { + sym::CallOnceFuture => { + let tupled_upvars_ty = Ty::new_projection( + tcx, + upvars_projection_def_id, + [ + ty::GenericArg::from(kind_ty), + Ty::from_closure_kind(tcx, goal_kind).into(), + env_region.into(), + sig.tupled_inputs_ty.into(), + args.tupled_upvars_ty().into(), + args.coroutine_captures_by_ref_ty().into(), + ], + ); + let coroutine_ty = sig.to_coroutine( + tcx, + args.parent_args(), + tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ); + ( + ty::AliasTy::new( + tcx, + obligation.predicate.def_id, + [self_ty, sig.tupled_inputs_ty], + ), + coroutine_ty.into(), + ) + } + sym::CallMutFuture | sym::CallFuture => { + let tupled_upvars_ty = Ty::new_projection( + tcx, + upvars_projection_def_id, + [ + ty::GenericArg::from(kind_ty), + Ty::from_closure_kind(tcx, goal_kind).into(), + env_region.into(), + sig.tupled_inputs_ty.into(), + args.tupled_upvars_ty().into(), + args.coroutine_captures_by_ref_ty().into(), + ], + ); + let coroutine_ty = sig.to_coroutine( + tcx, + args.parent_args(), + tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ); + ( + ty::AliasTy::new( + tcx, + obligation.predicate.def_id, + [ + ty::GenericArg::from(self_ty), + sig.tupled_inputs_ty.into(), + env_region.into(), + ], + ), + coroutine_ty.into(), + ) + } + sym::Output => ( + ty::AliasTy::new(tcx, obligation.predicate.def_id, [self_ty, sig.tupled_inputs_ty]), + sig.return_ty.into(), + ), + name => bug!("no such associated type: {name}"), + }; + ty::ProjectionPredicate { projection_ty, term } + }); + + confirm_param_env_candidate(selcx, obligation, poly_cache_entry, true) + .with_addl_obligations(nested) +} + +fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + nested: Vec>, +) -> Progress<'tcx> { + let [ + // We already checked that the goal_kind >= closure_kind + _closure_kind_ty, + goal_kind_ty, + borrow_region, + tupled_inputs_ty, + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + ] = **obligation.predicate.args + else { + bug!(); + }; + + let predicate = ty::ProjectionPredicate { + projection_ty: ty::AliasTy::new( + selcx.tcx(), + obligation.predicate.def_id, + obligation.predicate.args, + ), + term: ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( + selcx.tcx(), + goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap(), + tupled_inputs_ty.expect_ty(), + tupled_upvars_ty.expect_ty(), + coroutine_captures_by_ref_ty.expect_ty(), + borrow_region.expect_region(), + ) + .into(), + }; + + confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) + .with_addl_obligations(nested) +} + fn confirm_param_env_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b354ebf111f4c..75aedd5cd22ca 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -117,9 +117,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_iterator_candidates(obligation, &mut candidates); } else if lang_items.async_iterator_trait() == Some(def_id) { self.assemble_async_iterator_candidates(obligation, &mut candidates); + } else if lang_items.async_fn_kind_helper() == Some(def_id) { + self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates); } self.assemble_closure_candidates(obligation, &mut candidates); + self.assemble_async_closure_candidates(obligation, &mut candidates); self.assemble_fn_pointer_candidates(obligation, &mut candidates); self.assemble_candidates_from_impls(obligation, &mut candidates); self.assemble_candidates_from_object_ty(obligation, &mut candidates); @@ -335,6 +338,49 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + fn assemble_async_closure_candidates( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + let Some(goal_kind) = + self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()) + else { + return; + }; + + match *obligation.self_ty().skip_binder().kind() { + ty::CoroutineClosure(_, args) => { + if let Some(closure_kind) = + args.as_coroutine_closure().kind_ty().to_opt_closure_kind() + && !closure_kind.extends(goal_kind) + { + return; + } + candidates.vec.push(AsyncClosureCandidate); + } + ty::Infer(ty::TyVar(_)) => { + candidates.ambiguous = true; + } + _ => {} + } + } + + fn assemble_async_fn_kind_helper_candidates( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + if let Some(closure_kind) = obligation.self_ty().skip_binder().to_opt_closure_kind() + && let Some(goal_kind) = + obligation.predicate.skip_binder().trait_ref.args.type_at(1).to_opt_closure_kind() + { + if closure_kind.extends(goal_kind) { + candidates.vec.push(AsyncFnKindHelperCandidate); + } + } + } + /// Implements one of the `Fn()` family for a fn pointer. fn assemble_fn_pointer_candidates( &mut self, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 74f388e53a3c9..79336a9d4e8f0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -83,6 +83,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure) } + AsyncClosureCandidate => { + let vtable_closure = self.confirm_async_closure_candidate(obligation)?; + ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure) + } + + AsyncFnKindHelperCandidate => ImplSource::Builtin(BuiltinImplSource::Misc, vec![]), + CoroutineCandidate => { let vtable_coroutine = self.confirm_coroutine_candidate(obligation)?; ImplSource::Builtin(BuiltinImplSource::Misc, vtable_coroutine) @@ -869,6 +876,49 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(nested) } + #[instrument(skip(self), level = "debug")] + fn confirm_async_closure_candidate( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + ) -> Result>, SelectionError<'tcx>> { + // Okay to skip binder because the args on closure types never + // touch bound regions, they just capture the in-scope + // type/region parameters. + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let ty::CoroutineClosure(closure_def_id, args) = *self_ty.kind() else { + bug!("async closure candidate for non-coroutine-closure {:?}", obligation); + }; + + let trait_ref = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| { + ty::TraitRef::new( + self.tcx(), + obligation.predicate.def_id(), + [self_ty, sig.tupled_inputs_ty], + ) + }); + + let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + + let goal_kind = + self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap(); + nested.push(obligation.with( + self.tcx(), + ty::TraitRef::from_lang_item( + self.tcx(), + LangItem::AsyncFnKindHelper, + obligation.cause.span, + [ + args.as_coroutine_closure().kind_ty(), + Ty::from_closure_kind(self.tcx(), goal_kind), + ], + ), + )); + + debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations"); + + Ok(nested) + } + /// In the case of closure types and fn pointers, /// we currently treat the input type parameters on the trait as /// outputs. This means that when we have a match we have only diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e79277b89c4ae..7f41c73b72f0d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1864,6 +1864,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ImplCandidate(..) | AutoImplCandidate | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -1894,6 +1896,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ImplCandidate(_) | AutoImplCandidate | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -1930,6 +1934,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ImplCandidate(..) | AutoImplCandidate | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -1946,6 +1952,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ImplCandidate(..) | AutoImplCandidate | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -2054,6 +2062,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ( ImplCandidate(_) | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -2066,6 +2076,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | TraitAliasCandidate, ImplCandidate(_) | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index af26616831fd0..8d1bdec66848c 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -101,6 +101,42 @@ fn fn_sig_for_fn_abi<'tcx>( bound_vars, ) } + ty::CoroutineClosure(def_id, args) => { + let sig = args.as_coroutine_closure().coroutine_closure_sig(); + let bound_vars = tcx.mk_bound_variable_kinds_from_iter( + sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BoundRegionKind::BrEnv, + }; + let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); + let env_ty = tcx.closure_env_ty( + Ty::new_coroutine_closure(tcx, def_id, args), + args.as_coroutine_closure().kind(), + env_region, + ); + + let sig = sig.skip_binder(); + ty::Binder::bind_with_vars( + tcx.mk_fn_sig( + iter::once(env_ty).chain([sig.tupled_inputs_ty]), + sig.to_coroutine_given_kind_and_upvars( + tcx, + args.as_coroutine_closure().parent_args(), + tcx.coroutine_for_closure(def_id), + args.as_coroutine_closure().kind(), + env_region, + args.as_coroutine_closure().tupled_upvars_ty(), + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), + ), + sig.c_variadic, + sig.unsafety, + sig.abi, + ), + bound_vars, + ) + } ty::Coroutine(did, args) => { let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let sig = args.as_coroutine().sig(); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index a5a2c53c7321b..50d27ed4cedbd 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -38,6 +38,7 @@ fn resolve_instance<'tcx>( debug!(" => nontrivial drop glue"); match *ty.kind() { ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Tuple(..) | ty::Adt(..) @@ -282,6 +283,16 @@ fn resolve_associated_item<'tcx>( tcx.item_name(trait_item_id) ), } + } else if tcx.async_fn_trait_kind_from_def_id(trait_ref.def_id).is_some() { + match *rcvr_args.type_at(0).kind() { + ty::CoroutineClosure(closure_def_id, args) => { + Some(Instance::new(closure_def_id, args)) + } + _ => bug!( + "no built-in definition for `{trait_ref}::{}` for non-lending-closure type", + tcx.item_name(trait_item_id) + ), + } } else { Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args) } diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs index 965873f163eff..b11d5643990de 100644 --- a/library/core/src/ops/async_function.rs +++ b/library/core/src/ops/async_function.rs @@ -106,3 +106,11 @@ mod impls { } } } + +mod internal_implementation_detail { + // TODO: needs a detailed explanation + #[cfg_attr(not(bootstrap), lang = "async_fn_kind_helper")] + trait AsyncFnKindHelper { + type Assoc<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>; + } +} From fc4fff40385252212b9921928927568f233ba02f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 25 Jan 2024 00:30:55 +0000 Subject: [PATCH 587/676] Build a shim to call async closures with different AsyncFn trait kinds --- .../src/interpret/terminator.rs | 1 + compiler/rustc_middle/src/mir/mono.rs | 1 + compiler/rustc_middle/src/mir/visit.rs | 1 + compiler/rustc_middle/src/ty/instance.rs | 23 +++- compiler/rustc_middle/src/ty/mod.rs | 1 + compiler/rustc_mir_transform/src/inline.rs | 1 + .../rustc_mir_transform/src/inline/cycle.rs | 1 + compiler/rustc_mir_transform/src/shim.rs | 121 +++++++++++++++++- compiler/rustc_monomorphize/src/collector.rs | 1 + .../rustc_monomorphize/src/partitioning.rs | 2 + .../rustc_smir/src/rustc_smir/convert/ty.rs | 1 + compiler/rustc_ty_utils/src/abi.rs | 15 ++- compiler/rustc_ty_utils/src/instance.rs | 17 ++- 13 files changed, 175 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index b7ffb4a16fc31..4c8f68b25b55d 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -545,6 +545,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 91fdf0b312991..4a29171d8bf72 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -402,6 +402,7 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceDef::FnPtrShim(..) | InstanceDef::Virtual(..) | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 591104ecc663d..6bc58adea0f83 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -345,6 +345,7 @@ macro_rules! make_mir_visitor { ty::InstanceDef::Virtual(_def_id, _) | ty::InstanceDef::ThreadLocalShim(_def_id) | ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } | + ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, target_kind: _ } | ty::InstanceDef::DropGlue(_def_id, None) => {} ty::InstanceDef::FnPtrShim(_def_id, ty) | diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 293fdb026b685..41ae136851ec1 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -82,11 +82,25 @@ pub enum InstanceDef<'tcx> { /// details on that). Virtual(DefId, usize), - /// `<[FnMut closure] as FnOnce>::call_once`. + /// `<[FnMut/Fn closure] as FnOnce>::call_once`. /// /// The `DefId` is the ID of the `call_once` method in `FnOnce`. + /// + /// This generates a body that will just borrow the (owned) self type, + /// and dispatch to the `FnMut::call_mut` instance for the closure. ClosureOnceShim { call_once: DefId, track_caller: bool }, + /// `<[FnMut/Fn coroutine-closure] as FnOnce>::call_once` or + /// `<[Fn coroutine-closure] as FnMut>::call_mut`. + /// + /// The body generated here differs significantly from the `ClosureOnceShim`, + /// since we need to generate a distinct coroutine type that will move the + /// closure's upvars *out* of the closure. + ConstructCoroutineInClosureShim { + coroutine_closure_def_id: DefId, + target_kind: ty::ClosureKind, + }, + /// Compiler-generated accessor for thread locals which returns a reference to the thread local /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking /// native support. @@ -168,6 +182,10 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::Intrinsic(def_id) | InstanceDef::ThreadLocalShim(def_id) | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ } + | ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id: def_id, + target_kind: _, + } | InstanceDef::DropGlue(def_id, _) | InstanceDef::CloneShim(def_id, _) | InstanceDef::FnPtrAddrShim(def_id, _) => def_id, @@ -187,6 +205,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::Virtual(..) | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => None, @@ -282,6 +301,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::FnPtrShim(..) | InstanceDef::DropGlue(_, Some(_)) => false, InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::Item(_) | InstanceDef::Intrinsic(..) @@ -319,6 +339,7 @@ fn fmt_instance( InstanceDef::Virtual(_, num) => write!(f, " - virtual#{num}"), InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"), + InstanceDef::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"), InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4348d01eff58c..05875a9798bd8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1680,6 +1680,7 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::Virtual(..) | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) | ty::InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 67668a216dee3..7c731b070a748 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -317,6 +317,7 @@ impl<'tcx> Inliner<'tcx> { | InstanceDef::ReifyShim(_) | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index d30e0bad81301..3f3dc9145b632 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -87,6 +87,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( | InstanceDef::ReifyShim(_) | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } | InstanceDef::ThreadLocalShim { .. } | InstanceDef::CloneShim(..) => {} diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 89414ce940e05..29b83f58ef5db 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -3,8 +3,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt}; +use rustc_middle::ty::{GenericArgs, CAPTURE_STRUCT_LOCAL}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_index::{Idx, IndexVec}; @@ -66,6 +66,21 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut)) } + ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id, + target_kind, + } => match target_kind { + ty::ClosureKind::Fn => unreachable!("shouldn't be building shim for Fn"), + ty::ClosureKind::FnMut => { + let body = build_construct_coroutine_by_mut_shim(tcx, coroutine_closure_def_id); + // No need to optimize the body, it has already been optimized. + return body; + } + ty::ClosureKind::FnOnce => { + build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id) + } + }, + ty::InstanceDef::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? @@ -981,3 +996,107 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t let source = MirSource::from_instance(ty::InstanceDef::FnPtrAddrShim(def_id, self_ty)); new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span) } + +fn build_construct_coroutine_by_move_shim<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_closure_def_id: DefId, +) -> Body<'tcx> { + let self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity(); + let ty::CoroutineClosure(_, args) = *self_ty.kind() else { + bug!(); + }; + + let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| { + tcx.mk_fn_sig( + [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()), + sig.to_coroutine_given_kind_and_upvars( + tcx, + args.as_coroutine_closure().parent_args(), + tcx.coroutine_for_closure(coroutine_closure_def_id), + ty::ClosureKind::FnOnce, + tcx.lifetimes.re_erased, + args.as_coroutine_closure().tupled_upvars_ty(), + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), + ), + sig.c_variadic, + sig.unsafety, + sig.abi, + ) + }); + let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig); + let ty::Coroutine(coroutine_def_id, coroutine_args) = *sig.output().kind() else { + bug!(); + }; + + let span = tcx.def_span(coroutine_closure_def_id); + let locals = local_decls_for_sig(&sig, span); + + let mut fields = vec![]; + for idx in 1..sig.inputs().len() { + fields.push(Operand::Move(Local::from_usize(idx + 1).into())); + } + for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() { + fields.push(Operand::Move(tcx.mk_place_field( + Local::from_usize(1).into(), + FieldIdx::from_usize(idx), + ty, + ))); + } + + let source_info = SourceInfo::outermost(span); + let rvalue = Rvalue::Aggregate( + Box::new(AggregateKind::Coroutine(coroutine_def_id, coroutine_args)), + IndexVec::from_raw(fields), + ); + let stmt = Statement { + source_info, + kind: StatementKind::Assign(Box::new((Place::return_place(), rvalue))), + }; + let statements = vec![stmt]; + let start_block = BasicBlockData { + statements, + terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), + is_cleanup: false, + }; + + let source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id, + target_kind: ty::ClosureKind::FnOnce, + }); + + new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span) +} + +fn build_construct_coroutine_by_mut_shim<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_closure_def_id: DefId, +) -> Body<'tcx> { + let mut body = tcx.optimized_mir(coroutine_closure_def_id).clone(); + let coroutine_closure_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity(); + let ty::CoroutineClosure(_, args) = *coroutine_closure_ty.kind() else { + bug!(); + }; + let args = args.as_coroutine_closure(); + + body.local_decls[RETURN_PLACE].ty = + tcx.instantiate_bound_regions_with_erased(args.coroutine_closure_sig().map_bound(|sig| { + sig.to_coroutine_given_kind_and_upvars( + tcx, + args.parent_args(), + tcx.coroutine_for_closure(coroutine_closure_def_id), + ty::ClosureKind::FnMut, + tcx.lifetimes.re_erased, + args.tupled_upvars_ty(), + args.coroutine_captures_by_ref_ty(), + ) + })); + body.local_decls[CAPTURE_STRUCT_LOCAL].ty = + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_closure_ty); + + body.source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id, + target_kind: ty::ClosureKind::FnMut, + }); + + body +} diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b86244e5a4bfd..698fd63411412 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -983,6 +983,7 @@ fn visit_instance_use<'tcx>( | ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } | ty::InstanceDef::Item(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 7ff182381b835..46bd33c89e7e9 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -620,6 +620,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } | ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::Virtual(..) @@ -783,6 +784,7 @@ fn mono_item_visibility<'tcx>( | InstanceDef::Virtual(..) | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index e3fd64eb1891e..e0e9815cf40cd 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -799,6 +799,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::FnPtrAddrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } | ty::InstanceDef::ThreadLocalShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 8d1bdec66848c..3ea48ee824d47 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -111,11 +111,14 @@ fn fn_sig_for_fn_abi<'tcx>( kind: ty::BoundRegionKind::BrEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); - let env_ty = tcx.closure_env_ty( - Ty::new_coroutine_closure(tcx, def_id, args), - args.as_coroutine_closure().kind(), - env_region, - ); + + let mut kind = args.as_coroutine_closure().kind(); + if let InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. } = instance.def { + kind = target_kind; + } + + let env_ty = + tcx.closure_env_ty(Ty::new_coroutine_closure(tcx, def_id, args), kind, env_region); let sig = sig.skip_binder(); ty::Binder::bind_with_vars( @@ -125,7 +128,7 @@ fn fn_sig_for_fn_abi<'tcx>( tcx, args.as_coroutine_closure().parent_args(), tcx.coroutine_for_closure(def_id), - args.as_coroutine_closure().kind(), + kind, env_region, args.as_coroutine_closure().tupled_upvars_ty(), args.as_coroutine_closure().coroutine_captures_by_ref_ty(), diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 50d27ed4cedbd..fc224d242db6d 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -283,10 +283,21 @@ fn resolve_associated_item<'tcx>( tcx.item_name(trait_item_id) ), } - } else if tcx.async_fn_trait_kind_from_def_id(trait_ref.def_id).is_some() { + } else if let Some(target_kind) = tcx.async_fn_trait_kind_from_def_id(trait_ref.def_id) + { match *rcvr_args.type_at(0).kind() { - ty::CoroutineClosure(closure_def_id, args) => { - Some(Instance::new(closure_def_id, args)) + ty::CoroutineClosure(coroutine_closure_def_id, args) => { + if target_kind > args.as_coroutine_closure().kind() { + Some(Instance { + def: ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id, + target_kind, + }, + args, + }) + } else { + Some(Instance::new(coroutine_closure_def_id, args)) + } } _ => bug!( "no built-in definition for `{trait_ref}::{}` for non-lending-closure type", From 427896dd7e39f1aaf3e3cbc15e5ddf77d45a6aec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jan 2024 23:38:33 +0000 Subject: [PATCH 588/676] Construct body for by-move coroutine closure output --- .../src/type_check/input_output.rs | 1 + .../src/interpret/terminator.rs | 1 + compiler/rustc_hir_typeck/src/callee.rs | 1 + compiler/rustc_hir_typeck/src/closure.rs | 11 ++ compiler/rustc_hir_typeck/src/upvar.rs | 10 ++ compiler/rustc_middle/src/mir/mod.rs | 5 + compiler/rustc_middle/src/mir/mono.rs | 1 + compiler/rustc_middle/src/mir/visit.rs | 1 + compiler/rustc_middle/src/ty/instance.rs | 21 +++- compiler/rustc_middle/src/ty/mod.rs | 1 + compiler/rustc_middle/src/ty/sty.rs | 47 ++++++-- compiler/rustc_mir_transform/src/coroutine.rs | 3 + .../src/coroutine/by_move_body.rs | 108 ++++++++++++++++++ compiler/rustc_mir_transform/src/inline.rs | 1 + .../rustc_mir_transform/src/inline/cycle.rs | 1 + compiler/rustc_mir_transform/src/lib.rs | 4 + .../rustc_mir_transform/src/pass_manager.rs | 6 + compiler/rustc_mir_transform/src/shim.rs | 12 ++ compiler/rustc_monomorphize/src/collector.rs | 3 +- .../rustc_monomorphize/src/partitioning.rs | 4 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 1 + .../src/solve/assembly/structural_traits.rs | 1 + .../src/traits/project.rs | 2 + ...await.b-{closure#0}.coroutine_resume.0.mir | 2 + 24 files changed, 233 insertions(+), 15 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/coroutine/by_move_body.rs diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index a3e5088ee09aa..ace9c5ae71d6e 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -85,6 +85,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.tcx(), ty::CoroutineArgsParts { parent_args: args.parent_args(), + kind_ty: Ty::from_closure_kind(self.tcx(), args.kind()), resume_ty: next_ty_var(), yield_ty: next_ty_var(), witness: next_ty_var(), diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 4c8f68b25b55d..b8d6836da14a8 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -546,6 +546,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineByMoveShim { .. } | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 1858b2770cdbc..730a475f63049 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -183,6 +183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coroutine_closure_sig.to_coroutine( self.tcx, closure_args.parent_args(), + closure_args.kind_ty(), self.tcx.coroutine_for_closure(def_id), tupled_upvars_ty, ), diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 1d024efdd499f..014293c1f8325 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -175,10 +175,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { interior, )); + let kind_ty = match kind { + hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) => self + .next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }), + _ => tcx.types.unit, + }; + let coroutine_args = ty::CoroutineArgs::new( tcx, ty::CoroutineArgsParts { parent_args, + kind_ty, resume_ty, yield_ty, return_ty: liberated_sig.output(), @@ -256,6 +266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sig.to_coroutine( tcx, parent_args, + closure_kind_ty, tcx.coroutine_for_closure(expr_def_id), coroutine_upvars_ty, ) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index b087d6d9e570d..d4e072976fa69 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -393,6 +393,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args.as_coroutine_closure().coroutine_captures_by_ref_ty(), coroutine_captures_by_ref_ty, ); + + let ty::Coroutine(_, args) = *self.typeck_results.borrow().expr_ty(body.value).kind() + else { + bug!(); + }; + self.demand_eqtype( + span, + args.as_coroutine().kind_ty(), + Ty::from_closure_kind(self.tcx, closure_kind), + ); } self.log_closure_min_capture_info(closure_def_id, span); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index c9e69253701c5..d88e9261e5a1b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -262,6 +262,10 @@ pub struct CoroutineInfo<'tcx> { /// Coroutine drop glue. This field is populated after the state transform pass. pub coroutine_drop: Option>, + /// The body of the coroutine, modified to take its upvars by move. + /// TODO: + pub by_move_body: Option>, + /// The layout of a coroutine. This field is populated after the state transform pass. pub coroutine_layout: Option>, @@ -281,6 +285,7 @@ impl<'tcx> CoroutineInfo<'tcx> { coroutine_kind, yield_ty: Some(yield_ty), resume_ty: Some(resume_ty), + by_move_body: None, coroutine_drop: None, coroutine_layout: None, } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 4a29171d8bf72..e6d1535fdf2f6 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -403,6 +403,7 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceDef::Virtual(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineByMoveShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 6bc58adea0f83..ce1859d6adae3 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -346,6 +346,7 @@ macro_rules! make_mir_visitor { ty::InstanceDef::ThreadLocalShim(_def_id) | ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } | ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, target_kind: _ } | + ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id: _def_id } | ty::InstanceDef::DropGlue(_def_id, None) => {} ty::InstanceDef::FnPtrShim(_def_id, ty) | diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 41ae136851ec1..44bf3c32b487d 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -101,6 +101,9 @@ pub enum InstanceDef<'tcx> { target_kind: ty::ClosureKind, }, + /// TODO: + CoroutineByMoveShim { coroutine_def_id: DefId }, + /// Compiler-generated accessor for thread locals which returns a reference to the thread local /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking /// native support. @@ -186,6 +189,7 @@ impl<'tcx> InstanceDef<'tcx> { coroutine_closure_def_id: def_id, target_kind: _, } + | ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id: def_id } | InstanceDef::DropGlue(def_id, _) | InstanceDef::CloneShim(def_id, _) | InstanceDef::FnPtrAddrShim(def_id, _) => def_id, @@ -206,6 +210,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineByMoveShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => None, @@ -302,6 +307,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::DropGlue(_, Some(_)) => false, InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineByMoveShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::Item(_) | InstanceDef::Intrinsic(..) @@ -340,6 +346,7 @@ fn fmt_instance( InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"), InstanceDef::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), + InstanceDef::CoroutineByMoveShim { .. } => write!(f, " - shim"), InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"), InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"), @@ -631,7 +638,19 @@ impl<'tcx> Instance<'tcx> { }; if tcx.lang_items().get(coroutine_callable_item) == Some(trait_item_id) { - Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args }) + let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind() + else { + bug!() + }; + + if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() { + Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args }) + } else { + Some(Instance { + def: ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id }, + args, + }) + } } else { // All other methods should be defaulted methods of the built-in trait. // This is important for `Iterator`'s combinators, but also useful for diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 05875a9798bd8..9ceb3ec3f615c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1681,6 +1681,7 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceDef::Virtual(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineByMoveShim { .. } | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) | ty::InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e2a2e24f06dd8..8918a3735d618 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -399,6 +399,7 @@ impl<'tcx> CoroutineClosureSignature<'tcx> { self, tcx: TyCtxt<'tcx>, parent_args: &'tcx [GenericArg<'tcx>], + kind_ty: Ty<'tcx>, coroutine_def_id: DefId, tupled_upvars_ty: Ty<'tcx>, ) -> Ty<'tcx> { @@ -406,6 +407,7 @@ impl<'tcx> CoroutineClosureSignature<'tcx> { tcx, ty::CoroutineArgsParts { parent_args, + kind_ty, resume_ty: self.resume_ty, yield_ty: self.yield_ty, return_ty: self.return_ty, @@ -436,7 +438,13 @@ impl<'tcx> CoroutineClosureSignature<'tcx> { env_region, ); - self.to_coroutine(tcx, parent_args, coroutine_def_id, tupled_upvars_ty) + self.to_coroutine( + tcx, + parent_args, + Ty::from_closure_kind(tcx, closure_kind), + coroutine_def_id, + tupled_upvars_ty, + ) } /// Given a closure kind, compute the tupled upvars that the given coroutine would return. @@ -488,6 +496,8 @@ pub struct CoroutineArgs<'tcx> { pub struct CoroutineArgsParts<'tcx> { /// This is the args of the typeck root. pub parent_args: &'tcx [GenericArg<'tcx>], + // TODO: why + pub kind_ty: Ty<'tcx>, pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, pub return_ty: Ty<'tcx>, @@ -506,6 +516,7 @@ impl<'tcx> CoroutineArgs<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, parts: CoroutineArgsParts<'tcx>) -> CoroutineArgs<'tcx> { CoroutineArgs { args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.kind_ty.into(), parts.resume_ty.into(), parts.yield_ty.into(), parts.return_ty.into(), @@ -519,16 +530,23 @@ impl<'tcx> CoroutineArgs<'tcx> { /// The ordering assumed here must match that used by `CoroutineArgs::new` above. fn split(self) -> CoroutineArgsParts<'tcx> { match self.args[..] { - [ref parent_args @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { - CoroutineArgsParts { - parent_args, - resume_ty: resume_ty.expect_ty(), - yield_ty: yield_ty.expect_ty(), - return_ty: return_ty.expect_ty(), - witness: witness.expect_ty(), - tupled_upvars_ty: tupled_upvars_ty.expect_ty(), - } - } + [ + ref parent_args @ .., + kind_ty, + resume_ty, + yield_ty, + return_ty, + witness, + tupled_upvars_ty, + ] => CoroutineArgsParts { + parent_args, + kind_ty: kind_ty.expect_ty(), + resume_ty: resume_ty.expect_ty(), + yield_ty: yield_ty.expect_ty(), + return_ty: return_ty.expect_ty(), + witness: witness.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + }, _ => bug!("coroutine args missing synthetics"), } } @@ -538,6 +556,11 @@ impl<'tcx> CoroutineArgs<'tcx> { self.split().parent_args } + // TODO: + pub fn kind_ty(self) -> Ty<'tcx> { + self.split().kind_ty + } + /// This describes the types that can be contained in a coroutine. /// It will be a type variable initially and unified in the last stages of typeck of a body. /// It contains a tuple of all the types that could end up on a coroutine frame. @@ -1628,7 +1651,7 @@ impl<'tcx> Ty<'tcx> { ) -> Ty<'tcx> { debug_assert_eq!( coroutine_args.len(), - tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 6, "coroutine constructed with incorrect number of substitutions" ); Ty::new(tcx, Coroutine(def_id, coroutine_args)) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index bde879f6067c5..297b2fa143de2 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -50,6 +50,9 @@ //! For coroutines with state 1 (returned) and state 2 (poisoned) it does nothing. //! Otherwise it drops all the values in scope at the last suspension point. +mod by_move_body; +pub use by_move_body::ByMoveBody; + use crate::abort_unwinding_calls; use crate::deref_separator::deref_finder; use crate::errors; diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs new file mode 100644 index 0000000000000..4e3e70bdafef1 --- /dev/null +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -0,0 +1,108 @@ +use rustc_data_structures::fx::FxIndexSet; +use rustc_hir as hir; +use rustc_middle::mir::visit::MutVisitor; +use rustc_middle::mir::{self, MirPass}; +use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt}; +use rustc_target::abi::FieldIdx; + +pub struct ByMoveBody; + +impl<'tcx> MirPass<'tcx> for ByMoveBody { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { + let Some(coroutine_def_id) = body.source.def_id().as_local() else { + return; + }; + let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = + tcx.coroutine_kind(coroutine_def_id) + else { + return; + }; + let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; + let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!() }; + if args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() == ty::ClosureKind::FnOnce { + return; + } + + let mut by_ref_fields = FxIndexSet::default(); + let by_move_upvars = Ty::new_tup_from_iter( + tcx, + tcx.closure_captures(coroutine_def_id).iter().enumerate().map(|(idx, capture)| { + if capture.is_by_ref() { + by_ref_fields.insert(FieldIdx::from_usize(idx)); + } + capture.place.ty() + }), + ); + let by_move_coroutine_ty = Ty::new_coroutine( + tcx, + coroutine_def_id.to_def_id(), + ty::CoroutineArgs::new( + tcx, + ty::CoroutineArgsParts { + parent_args: args.as_coroutine().parent_args(), + kind_ty: Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce), + resume_ty: args.as_coroutine().resume_ty(), + yield_ty: args.as_coroutine().yield_ty(), + return_ty: args.as_coroutine().return_ty(), + witness: args.as_coroutine().witness(), + tupled_upvars_ty: by_move_upvars, + }, + ) + .args, + ); + + let mut by_move_body = body.clone(); + MakeByMoveBody { tcx, by_ref_fields, by_move_coroutine_ty }.visit_body(&mut by_move_body); + by_move_body.source = mir::MirSource { + instance: InstanceDef::CoroutineByMoveShim { + coroutine_def_id: coroutine_def_id.to_def_id(), + }, + promoted: None, + }; + + body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body); + } +} + +struct MakeByMoveBody<'tcx> { + tcx: TyCtxt<'tcx>, + by_ref_fields: FxIndexSet, + by_move_coroutine_ty: Ty<'tcx>, +} + +impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_place( + &mut self, + place: &mut mir::Place<'tcx>, + context: mir::visit::PlaceContext, + location: mir::Location, + ) { + if place.local == ty::CAPTURE_STRUCT_LOCAL + && !place.projection.is_empty() + && let mir::ProjectionElem::Field(idx, ty) = place.projection[0] + && self.by_ref_fields.contains(&idx) + { + let (begin, end) = place.projection[1..].split_first().unwrap(); + assert_eq!(*begin, mir::ProjectionElem::Deref); + *place = mir::Place { + local: place.local, + projection: self.tcx.mk_place_elems_from_iter( + [mir::ProjectionElem::Field(idx, ty.builtin_deref(true).unwrap().ty)] + .into_iter() + .chain(end.iter().copied()), + ), + }; + } + self.super_place(place, context, location); + } + + fn visit_local_decl(&mut self, local: mir::Local, local_decl: &mut mir::LocalDecl<'tcx>) { + if local == ty::CAPTURE_STRUCT_LOCAL { + local_decl.ty = self.by_move_coroutine_ty; + } + } +} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 7c731b070a748..24bc84a235c2d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -318,6 +318,7 @@ impl<'tcx> Inliner<'tcx> { | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineByMoveShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 3f3dc9145b632..77ff780393efb 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -88,6 +88,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineByMoveShim { .. } | InstanceDef::ThreadLocalShim { .. } | InstanceDef::CloneShim(..) => {} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 69f93fa3a0e21..031515ea95828 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -307,6 +307,10 @@ fn mir_const(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { &Lint(check_packed_ref::CheckPackedRef), &Lint(check_const_item_mutation::CheckConstItemMutation), &Lint(function_item_references::FunctionItemReferences), + // If this is an async closure's output coroutine, generate + // by-move and by-mut bodies if needed. We do this first so + // they can be optimized in lockstep with their parent bodies. + &coroutine::ByMoveBody, // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, &rustc_peek::SanityCheck, // Just a lint diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index c1ef2b9f887fb..c7e770904fbb8 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -189,6 +189,12 @@ fn run_passes_inner<'tcx>( body.pass_count = 1; } + + if let Some(coroutine) = body.coroutine.as_mut() + && let Some(by_move_body) = coroutine.by_move_body.as_mut() + { + run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each); + } } pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 29b83f58ef5db..668ccdd873550 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -81,6 +81,18 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' } }, + ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id } => { + return tcx + .optimized_mir(coroutine_def_id) + .coroutine + .as_ref() + .unwrap() + .by_move_body + .as_ref() + .unwrap() + .clone(); + } + ty::InstanceDef::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 698fd63411412..cf3c8e1fdd3b4 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -983,7 +983,8 @@ fn visit_instance_use<'tcx>( | ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } - | InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineByMoveShim { .. } | ty::InstanceDef::Item(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 46bd33c89e7e9..22b35c4344b86 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -620,7 +620,8 @@ fn characteristic_def_id_of_mono_item<'tcx>( | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } - | InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineByMoveShim { .. } | ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::Virtual(..) @@ -785,6 +786,7 @@ fn mono_item_visibility<'tcx>( | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineByMoveShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index e0e9815cf40cd..3c1858e920b04 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -800,6 +800,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceDef::FnPtrAddrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineByMoveShim { .. } | ty::InstanceDef::ThreadLocalShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index c35134c78eb16..0699026117dae 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -366,6 +366,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc let coroutine_ty = sig.to_coroutine( tcx, args.parent_args(), + Ty::from_closure_kind(tcx, goal_kind), tcx.coroutine_for_closure(def_id), tupled_upvars_ty, ); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 648f14beaa7a3..db1e89ae72fdf 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2505,6 +2505,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( let coroutine_ty = sig.to_coroutine( tcx, args.parent_args(), + Ty::from_closure_kind(tcx, goal_kind), tcx.coroutine_for_closure(def_id), tupled_upvars_ty, ); @@ -2533,6 +2534,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( let coroutine_ty = sig.to_coroutine( tcx, args.parent_args(), + Ty::from_closure_kind(tcx, goal_kind), tcx.coroutine_for_closure(def_id), tupled_upvars_ty, ); diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 3c0d4008c9018..9c8cf8763fdf1 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -5,6 +5,7 @@ ty: Coroutine( DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), [ + (), std::future::ResumeTy, (), (), @@ -22,6 +23,7 @@ ty: Coroutine( DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), [ + (), std::future::ResumeTy, (), (), From 881b6b5149e882434a8df80a829bcfde0a2e9d37 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 25 Jan 2024 03:50:23 +0000 Subject: [PATCH 589/676] Bless tests, add comments --- .../src/type_check/input_output.rs | 5 +- .../rustc_borrowck/src/universal_regions.rs | 5 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 12 ++- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/traits/select.rs | 4 +- compiler/rustc_middle/src/ty/instance.rs | 5 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 36 +++++++- .../rustc_smir/src/rustc_smir/convert/mir.rs | 2 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../src/solve/assembly/mod.rs | 4 +- .../src/solve/assembly/structural_traits.rs | 13 +-- .../src/traits/project.rs | 14 +-- compiler/rustc_type_ir/src/ty_kind.rs | 6 +- library/core/src/ops/async_function.rs | 21 ++++- .../async-borrowck-escaping-closure-error.rs | 3 +- ...ync-borrowck-escaping-closure-error.stderr | 28 +++--- .../async-closures/higher-ranked.rs | 4 +- .../async-closures/higher-ranked.stderr | 17 ---- .../issue-74072-lifetime-name-annotations.rs | 6 +- ...sue-74072-lifetime-name-annotations.stderr | 90 +++++++++++++------ .../binder/async-closure-with-binder.rs | 7 +- .../binder/async-closure-with-binder.stderr | 16 ---- ...rg-where-it-should-have-been-called.stderr | 12 +-- tests/ui/symbol-names/basic.legacy.stderr | 4 +- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- 28 files changed, 201 insertions(+), 126 deletions(-) delete mode 100644 tests/ui/async-await/async-closures/higher-ranked.stderr delete mode 100644 tests/ui/closures/binder/async-closure-with-binder.stderr diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index ace9c5ae71d6e..46fd0ce2b39a0 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -47,8 +47,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_provided_sig, ); - // FIXME(async_closures): We must apply the same transformation to our - // signature here as we do during closure checking. + // FIXME(async_closures): It's kind of wacky that we must apply this + // transformation here, since we do the same thing in HIR typeck. + // Maybe we could just fix up the canonicalized signature during HIR typeck? if let DefiningTy::CoroutineClosure(_, args) = self.borrowck_context.universal_regions.defining_ty { diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 9c266d123b338..d696e624823af 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -98,7 +98,10 @@ pub enum DefiningTy<'tcx> { Coroutine(DefId, GenericArgsRef<'tcx>), /// The MIR is a special kind of closure that returns coroutines. - /// TODO: describe how to make the sig... + /// + /// See the documentation on `CoroutineClosureSignature` for details + /// on how to construct the callable signature of the coroutine from + /// its args. CoroutineClosure(DefId, GenericArgsRef<'tcx>), /// The MIR is a fn item with the given `DefId` and args. The signature diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d30c7a4fb3899..23fb7eba65606 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -335,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } - // For this check, we do *not* want to treat async coroutine closures (async blocks) + // For this check, we do *not* want to treat async coroutine-closures (async blocks) // as proper closures. Doing so would regress type inference when feeding // the return value of an argument-position async block to an argument-position // closure wrapped in a block. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index d88e9261e5a1b..3d6c28088ad59 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -262,8 +262,16 @@ pub struct CoroutineInfo<'tcx> { /// Coroutine drop glue. This field is populated after the state transform pass. pub coroutine_drop: Option>, - /// The body of the coroutine, modified to take its upvars by move. - /// TODO: + /// The body of the coroutine, modified to take its upvars by move rather than by ref. + /// + /// This is used by coroutine-closures, which must return a different flavor of coroutine + /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` which + /// is run right after building the initial MIR, and will only be populated for coroutines + /// which come out of the async closure desugaring. + /// + /// This body should be processed in lockstep with the containing body -- any optimization + /// passes, etc, should be applied to this body as well. This is done automatically if + /// using `run_passes`. pub by_move_body: Option>, /// The layout of a coroutine. This field is populated after the state transform pass. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index f9ab32b16f534..938fba0ed0981 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -756,7 +756,7 @@ rustc_queries! { } query coroutine_for_closure(def_id: DefId) -> DefId { - desc { |_tcx| "TODO" } + desc { |_tcx| "Given a coroutine-closure def id, return the def id of the coroutine returned by it" } separate_provide_extern } diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 4e11575cf9800..28eba133c76df 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -138,7 +138,9 @@ pub enum SelectionCandidate<'tcx> { /// generated for an `async ||` expression. AsyncClosureCandidate, - // TODO: + /// Implementation of the the `AsyncFnKindHelper` helper trait, which + /// is used internally to delay computation for async closures until after + /// upvar analysis is performed in HIR typeck. AsyncFnKindHelperCandidate, /// Implementation of a `Coroutine` trait by one of the anonymous types diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 44bf3c32b487d..2c80dd021451f 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -101,7 +101,10 @@ pub enum InstanceDef<'tcx> { target_kind: ty::ClosureKind, }, - /// TODO: + /// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce` + /// is called on a coroutine-closure whose closure kind is not `FnOnce`. This + /// will select the body that is produced by the `ByMoveBody` transform, and thus + /// take and use all of its upvars by-move rather than by-ref. CoroutineByMoveShim { coroutine_def_id: DefId }, /// Compiler-generated accessor for thread locals which returns a reference to the thread local diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index be6b887ba7dc6..c0bfd2380ade0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -877,7 +877,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::CoroutineClosure(did, args) => { p!(write("{{")); if !self.should_print_verbose() { - p!(write("coroutine closure")); + p!(write("coroutine-closure")); // FIXME(eddyb) should use `def_span`. if let Some(did) = did.as_local() { if self.tcx().sess.opts.unstable_opts.span_free_formats { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8918a3735d618..3bbebaddbdd33 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -276,11 +276,31 @@ pub struct CoroutineClosureArgs<'tcx> { } pub struct CoroutineClosureArgsParts<'tcx> { + /// This is the args of the typeck root. pub parent_args: &'tcx [GenericArg<'tcx>], + /// Represents the maximum calling capability of the closure. pub closure_kind_ty: Ty<'tcx>, + /// Represents all of the relevant parts of the coroutine returned by this + /// coroutine-closure. This signature parts type will have the general + /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where + /// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the + /// coroutine returned by the coroutine-closure. + /// + /// Use `coroutine_closure_sig` to break up this type rather than using it + /// yourself. pub signature_parts_ty: Ty<'tcx>, + /// The upvars captured by the closure. Remains an inference variable + /// until the upvar analysis, which happens late in HIR typeck. pub tupled_upvars_ty: Ty<'tcx>, + /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`. + /// This allows us to represent the binder of the self-captures of the closure. + /// + /// For example, if the coroutine returned by the closure borrows `String` + /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`, + /// while the `tupled_upvars_ty`, representing the by-move version of the same + /// captures, will be `(String,)`. pub coroutine_captures_by_ref_ty: Ty<'tcx>, + /// Witness type returned by the generator produced by this coroutine-closure. pub coroutine_witness_ty: Ty<'tcx>, } @@ -496,15 +516,27 @@ pub struct CoroutineArgs<'tcx> { pub struct CoroutineArgsParts<'tcx> { /// This is the args of the typeck root. pub parent_args: &'tcx [GenericArg<'tcx>], - // TODO: why + + /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut` + /// implementations must be distinguished since the former takes the closure's + /// upvars by move, and the latter takes the closure's upvars by ref. + /// + /// This field distinguishes these fields so that codegen can select the right + /// body for the coroutine. This has the same type representation as the closure + /// kind: `i8`/`i16`/`i32`. + /// + /// For regular coroutines, this field will always just be `()`. pub kind_ty: Ty<'tcx>, + pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, pub return_ty: Ty<'tcx>, + /// The interior type of the coroutine. /// Represents all types that are stored in locals /// in the coroutine's body. pub witness: Ty<'tcx>, + /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. pub tupled_upvars_ty: Ty<'tcx>, @@ -556,7 +588,7 @@ impl<'tcx> CoroutineArgs<'tcx> { self.split().parent_args } - // TODO: + // Returns the kind of the coroutine. See docs on the `kind_ty` field. pub fn kind_ty(self) -> Ty<'tcx> { self.split().kind_ty } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 65ff85a96695b..41a4edfc03b58 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -539,7 +539,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { ) } mir::AggregateKind::CoroutineClosure(..) => { - todo!("FIXME(async_closure): Lower these to SMIR") + todo!("FIXME(async_closures): Lower these to SMIR") } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 3c1858e920b04..066348dcb67bc 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -383,7 +383,7 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { tables.closure_def(*def_id), generic_args.stable(tables), )), - ty::CoroutineClosure(..) => todo!("/* TODO */"), + ty::CoroutineClosure(..) => todo!("FIXME(async_closures): Lower these to SMIR"), ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine( tables.coroutine_def(*def_id), generic_args.stable(tables), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 587eb1c7cc5ae..4203cb29db6c5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -321,6 +321,7 @@ symbols! { TyCtxt, TyKind, Unknown, + Upvars, Vec, VecDeque, Wrapper, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 8451fbcc434cd..7052fd776b0f2 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -190,7 +190,9 @@ pub(super) trait GoalKind<'tcx>: kind: ty::ClosureKind, ) -> QueryResult<'tcx>; - /// TODO: + /// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which + /// is used internally to delay computation for async closures until after + /// upvar analysis is performed in HIR typeck. fn consider_builtin_async_fn_kind_helper_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 0699026117dae..dbf3e4876a960 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -8,6 +8,7 @@ use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{ self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; +use rustc_span::sym; use crate::solve::EvalCtxt; @@ -274,7 +275,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output())))) } - // Coroutine closures don't implement `Fn` traits the normal way. + // Coroutine-closures don't implement `Fn` traits the normal way. ty::CoroutineClosure(..) => Err(NoSolution), ty::Bool @@ -341,11 +342,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc vec![], )) } else { - let helper_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); - // FIXME(async_closures): Make this into a lang item. + let async_fn_kind_trait_def_id = + tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); let upvars_projection_def_id = tcx - .associated_items(helper_trait_def_id) - .in_definition_order() + .associated_items(async_fn_kind_trait_def_id) + .filter_by_name_unhygienic(sym::Upvars) .next() .unwrap() .def_id; @@ -375,7 +376,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc vec![ ty::TraitRef::new( tcx, - helper_trait_def_id, + async_fn_kind_trait_def_id, [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], ) .to_predicate(tcx), diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index db1e89ae72fdf..a8d6b9812be3a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2461,12 +2461,13 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( let goal_kind = tcx.async_fn_trait_kind_from_def_id(obligation.predicate.trait_def_id(tcx)).unwrap(); - let helper_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); + let async_fn_kind_helper_trait_def_id = + tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); nested.push(obligation.with( tcx, ty::TraitRef::new( tcx, - helper_trait_def_id, + async_fn_kind_helper_trait_def_id, [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], ), )); @@ -2476,9 +2477,12 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( ty::ClosureKind::FnOnce => tcx.lifetimes.re_static, }; - // FIXME(async_closures): Make this into a lang item. - let upvars_projection_def_id = - tcx.associated_items(helper_trait_def_id).in_definition_order().next().unwrap().def_id; + let upvars_projection_def_id = tcx + .associated_items(async_fn_kind_helper_trait_def_id) + .filter_by_name_unhygienic(sym::Upvars) + .next() + .unwrap() + .def_id; // FIXME(async_closures): Confirmation is kind of a mess here. Ideally, // we'd short-circuit when we know that the goal_kind >= closure_kind, and not diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 5941fce88250a..a4fe572067b03 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -202,7 +202,11 @@ pub enum TyKind { /// `ClosureArgs` for more details. Closure(I::DefId, I::GenericArgs), - /// TODO + /// The anonymous type of a closure. Used to represent the type of `async |a| a`. + /// + /// Coroutine-closure args contain both the - potentially substituted - generic + /// parameters of its parent and some synthetic parameters. See the documentation + /// for `CoroutineClosureArgs` for more details. CoroutineClosure(I::DefId, I::GenericArgs), /// The anonymous type of a coroutine. Used to represent the type of diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs index b11d5643990de..efbe9d164c3a7 100644 --- a/library/core/src/ops/async_function.rs +++ b/library/core/src/ops/async_function.rs @@ -108,9 +108,26 @@ mod impls { } mod internal_implementation_detail { - // TODO: needs a detailed explanation + /// A helper trait that is used to enforce that the `ClosureKind` of a goal + /// is within the capabilities of a `CoroutineClosure`, and which allows us + /// to delay the projection of the tupled upvar types until after upvar + /// analysis is complete. + /// + /// The `Self` type is expected to be the `kind_ty` of the coroutine-closure, + /// and thus either `?0` or `i8`/`i16`/`i32` (see docs for `ClosureKind` + /// for an explanation of that). The `GoalKind` is also the same type, but + /// representing the kind of the trait that the closure is being called with. #[cfg_attr(not(bootstrap), lang = "async_fn_kind_helper")] trait AsyncFnKindHelper { - type Assoc<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>; + // Projects a set of closure inputs (arguments), a region, and a set of upvars + // (by move and by ref) to the upvars that we expect the coroutine to have + // according to the `GoalKind` parameter above. + // + // The `Upvars` parameter should be the upvars of the parent coroutine-closure, + // and the `BorrowedUpvarsAsFnPtr` will be a function pointer that has the shape + // `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder + // of the closure's self-capture, and these upvar types will be instantiated with + // the `'closure_env` region provided to the associated type. + type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>; } } diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs index c02bac2d7dd49..2a3e382e11868 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -4,7 +4,8 @@ fn foo() -> Box> { let x = 0u32; Box::new((async || x)()) - //~^ ERROR closure may outlive the current function, but it borrows `x`, which is owned by the current function + //~^ ERROR cannot return value referencing local variable `x` + //~| ERROR cannot return value referencing temporary value } fn main() { diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr index 87851e1ae5be5..be67c78221a7c 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr @@ -1,21 +1,21 @@ -error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/async-borrowck-escaping-closure-error.rs:6:15 +error[E0515]: cannot return value referencing local variable `x` + --> $DIR/async-borrowck-escaping-closure-error.rs:6:5 | LL | Box::new((async || x)()) - | ^^^^^^^^ - `x` is borrowed here - | | - | may outlive borrowed value `x` - | -note: closure is returned here + | ^^^^^^^^^------------^^^ + | | | + | | `x` is borrowed here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value --> $DIR/async-borrowck-escaping-closure-error.rs:6:5 | LL | Box::new((async || x)()) - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword - | -LL | Box::new((async move || x)()) - | ++++ + | ^^^^^^^^^------------^^^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0373`. +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/async-await/async-closures/higher-ranked.rs b/tests/ui/async-await/async-closures/higher-ranked.rs index f0bdcf691ae2f..5bbcc7041a8f8 100644 --- a/tests/ui/async-await/async-closures/higher-ranked.rs +++ b/tests/ui/async-await/async-closures/higher-ranked.rs @@ -1,12 +1,10 @@ // edition:2021 +// check-pass #![feature(async_closure)] fn main() { let x = async move |x: &str| { - //~^ ERROR lifetime may not live long enough - // This error is proof that the `&str` type is higher-ranked. - // This won't work until async closures are fully impl'd. println!("{x}"); }; } diff --git a/tests/ui/async-await/async-closures/higher-ranked.stderr b/tests/ui/async-await/async-closures/higher-ranked.stderr deleted file mode 100644 index fb02a15b079d7..0000000000000 --- a/tests/ui/async-await/async-closures/higher-ranked.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/higher-ranked.rs:6:34 - | -LL | let x = async move |x: &str| { - | ____________________________-___-_^ - | | | | - | | | return type of closure `{async closure body@$DIR/higher-ranked.rs:6:34: 11:6}` contains a lifetime `'2` - | | let's call the lifetime of this reference `'1` -LL | | -LL | | // This error is proof that the `&str` type is higher-ranked. -LL | | // This won't work until async closures are fully impl'd. -LL | | println!("{x}"); -LL | | }; - | |_____^ returning this value requires that `'1` must outlive `'2` - -error: aborting due to 1 previous error - diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs index 2d453e7891e5f..904d28fb0a78d 100644 --- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs @@ -12,7 +12,8 @@ pub async fn async_fn(x: &mut i32) -> &i32 { pub fn async_closure(x: &mut i32) -> impl Future { (async move || { - //~^ captured variable cannot escape `FnMut` closure body + //~^ ERROR lifetime may not live long enough + //~| ERROR temporary value dropped while borrowed let y = &*x; *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed y @@ -21,7 +22,8 @@ pub fn async_closure(x: &mut i32) -> impl Future { pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future { (async move || -> &i32 { - //~^ captured variable cannot escape `FnMut` closure body + //~^ ERROR lifetime may not live long enough + //~| ERROR temporary value dropped while borrowed let y = &*x; *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed y diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr index 9120d78164e88..bdf2820887c8b 100644 --- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr @@ -11,7 +11,7 @@ LL | y | - returning this value requires that `*x` is borrowed for `'1` error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:17:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:18:9 | LL | let y = &*x; | --- `*x` is borrowed here @@ -22,61 +22,92 @@ LL | y LL | })() | - return type of async closure is &'1 i32 -error: captured variable cannot escape `FnMut` closure body +error: lifetime may not live long enough --> $DIR/issue-74072-lifetime-name-annotations.rs:14:20 | -LL | pub fn async_closure(x: &mut i32) -> impl Future { - | - variable defined here LL | (async move || { - | __________________-_^ - | | | - | | inferred to be a `FnMut` closure + | ______-------------_^ + | | | | + | | | return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:14:20: 20:6}` contains a lifetime `'2` + | | lifetime `'1` represents this closure's body +LL | | LL | | LL | | let y = &*x; - | | - variable captured here LL | | *x += 1; LL | | y LL | | })() - | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body + | |_____^ returning this value requires that `'1` must outlive `'2` + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure + +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:14:5 | - = note: `FnMut` closures only have access to their captured variables while they are executing... - = note: ...therefore, they cannot allow references to captured variables to escape +LL | pub fn async_closure(x: &mut i32) -> impl Future { + | - let's call the lifetime of this reference `'1` +LL | // (async move || { +LL | || +LL | || +LL | || let y = &*x; +LL | || *x += 1; +LL | || y +LL | || })() + | ||______^_- argument requires that borrow lasts for `'1` + | |_______| + | creates a temporary value which is freed while still in use +LL | } + | - temporary value is freed at the end of this statement error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:26:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:28:9 | -LL | (async move || -> &i32 { - | - let's call the lifetime of this reference `'1` -LL | LL | let y = &*x; | --- `*x` is borrowed here LL | *x += 1; | ^^^^^^^ `*x` is assigned to here but it was already borrowed LL | y | - returning this value requires that `*x` is borrowed for `'1` +LL | })() + | - return type of async closure is &'1 i32 -error: captured variable cannot escape `FnMut` closure body - --> $DIR/issue-74072-lifetime-name-annotations.rs:23:28 +error: lifetime may not live long enough + --> $DIR/issue-74072-lifetime-name-annotations.rs:24:28 | -LL | pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future { - | - variable defined here LL | (async move || -> &i32 { - | __________________________-_^ - | | | - | | inferred to be a `FnMut` closure + | ______---------------------_^ + | | | | + | | | return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:24:28: 30:6}` contains a lifetime `'2` + | | lifetime `'1` represents this closure's body +LL | | LL | | LL | | let y = &*x; - | | - variable captured here LL | | *x += 1; LL | | y LL | | })() - | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body + | |_____^ returning this value requires that `'1` must outlive `'2` + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure + +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:24:5 | - = note: `FnMut` closures only have access to their captured variables while they are executing... - = note: ...therefore, they cannot allow references to captured variables to escape +LL | pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future { + | - let's call the lifetime of this reference `'1` +LL | // (async move || -> &i32 { +LL | || +LL | || +LL | || let y = &*x; +LL | || *x += 1; +LL | || y +LL | || })() + | ||______^_- argument requires that borrow lasts for `'1` + | |_______| + | creates a temporary value which is freed while still in use +LL | } + | - temporary value is freed at the end of this statement error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:34:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:36:9 | LL | let y = &*x; | --- `*x` is borrowed here @@ -87,6 +118,7 @@ LL | y LL | } | - return type of async block is &'1 i32 -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0506`. +Some errors have detailed explanations: E0506, E0716. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/closures/binder/async-closure-with-binder.rs b/tests/ui/closures/binder/async-closure-with-binder.rs index 4fa599d37cbd1..69d30f369e97d 100644 --- a/tests/ui/closures/binder/async-closure-with-binder.rs +++ b/tests/ui/closures/binder/async-closure-with-binder.rs @@ -1,8 +1,9 @@ // edition:2021 +// check-pass + #![feature(closure_lifetime_binder)] #![feature(async_closure)] + fn main() { - for<'a> async || (); - //~^ ERROR `for<...>` binders on `async` closures are not currently supported - //~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + for<'a> async || -> () {}; } diff --git a/tests/ui/closures/binder/async-closure-with-binder.stderr b/tests/ui/closures/binder/async-closure-with-binder.stderr deleted file mode 100644 index 1d4628b1a494a..0000000000000 --- a/tests/ui/closures/binder/async-closure-with-binder.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: `for<...>` binders on `async` closures are not currently supported - --> $DIR/async-closure-with-binder.rs:5:5 - | -LL | for<'a> async || (); - | ^^^^^^^ - -error: implicit types in closure signatures are forbidden when `for<...>` is present - --> $DIR/async-closure-with-binder.rs:5:5 - | -LL | for<'a> async || (); - | -------^^^^^^^^^ - | | - | `for<...>` is here - -error: aborting due to 2 previous errors - diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 3065f83ea3d1b..dc4ec5d3ee28b 100644 --- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -18,25 +18,21 @@ help: use parentheses to call this function LL | bar(foo()); | ++ -error[E0277]: `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future +error[E0277]: `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 | LL | bar(async_closure); - | --- ^^^^^^^^^^^^^ `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future + | --- ^^^^^^^^^^^^^ `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for closure `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` - = note: {closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited + = help: the trait `Future` is not implemented for `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` + = note: {coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | LL | fn bar(f: impl Future) {} | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` -help: use parentheses to call this closure - | -LL | bar(async_closure()); - | ++ error: aborting due to 2 previous errors diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index 61d27ec69f4d2..c1cbefac828d6 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h9308686d0228fa1dE) +error: symbol-name(_ZN5basic4main17h6fc0c8d27b1a289fE) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h9308686d0228fa1d) +error: demangling(basic::main::h6fc0c8d27b1a289f) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index eb65f3b58fff8..7dd68e6e3a8e2 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h84ab5dafbd2a1508E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hab58a402db4ebf3aE) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h84ab5dafbd2a1508) +error: demangling(issue_60925::foo::Foo::foo::hab58a402db4ebf3a) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] From 37184e86ea58bc90b8cd97f877d52ccce8ea02ab Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 25 Jan 2024 17:43:35 +0000 Subject: [PATCH 590/676] Add some tests --- compiler/rustc_hir_typeck/src/upvar.rs | 5 ++-- .../src/traits/select/candidate_assembly.rs | 16 +++++++++--- .../async-closures/arg-mismatch.rs | 15 +++++++++++ .../async-closures/arg-mismatch.stderr | 21 +++++++++++++++ .../async-fn-once-for-async-fn.rs | 23 ++++++++++++++++ .../async-fn-once-for-async-fn.stderr | 2 ++ .../async-closures/auxiliary/block-on.rs | 20 ++++++++++++++ .../await-inference-guidance.rs | 16 ++++++++++++ tests/ui/async-await/async-closures/brand.rs | 26 +++++++++++++++++++ .../async-closures/higher-ranked-return.rs | 18 +++++++++++++ .../higher-ranked-return.stderr | 14 ++++++++++ .../async-closures/higher-ranked.rs | 14 +++++++--- .../async-await/async-closures/is-not-fn.rs | 12 +++++++++ .../async-closures/is-not-fn.stderr | 19 ++++++++++++++ .../async-closures/move-consuming-capture.rs | 20 ++++++++++++++ .../move-consuming-capture.stderr | 17 ++++++++++++ .../async-closures/move-is-async-fn.rs | 21 +++++++++++++++ tests/ui/async-await/async-closures/mutate.rs | 19 ++++++++++++++ .../async-await/async-closures/not-lending.rs | 21 +++++++++++++++ .../async-closures/not-lending.stderr | 24 +++++++++++++++++ .../async-closures/return-type-mismatch.rs | 14 ++++++++++ .../return-type-mismatch.stderr | 14 ++++++++++ .../async-closures/wrong-fn-kind.rs | 18 +++++++++++++ .../async-closures/wrong-fn-kind.stderr | 22 ++++++++++++++++ 24 files changed, 402 insertions(+), 9 deletions(-) create mode 100644 tests/ui/async-await/async-closures/arg-mismatch.rs create mode 100644 tests/ui/async-await/async-closures/arg-mismatch.stderr create mode 100644 tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs create mode 100644 tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr create mode 100644 tests/ui/async-await/async-closures/auxiliary/block-on.rs create mode 100644 tests/ui/async-await/async-closures/await-inference-guidance.rs create mode 100644 tests/ui/async-await/async-closures/brand.rs create mode 100644 tests/ui/async-await/async-closures/higher-ranked-return.rs create mode 100644 tests/ui/async-await/async-closures/higher-ranked-return.stderr create mode 100644 tests/ui/async-await/async-closures/is-not-fn.rs create mode 100644 tests/ui/async-await/async-closures/is-not-fn.stderr create mode 100644 tests/ui/async-await/async-closures/move-consuming-capture.rs create mode 100644 tests/ui/async-await/async-closures/move-consuming-capture.stderr create mode 100644 tests/ui/async-await/async-closures/move-is-async-fn.rs create mode 100644 tests/ui/async-await/async-closures/mutate.rs create mode 100644 tests/ui/async-await/async-closures/not-lending.rs create mode 100644 tests/ui/async-await/async-closures/not-lending.stderr create mode 100644 tests/ui/async-await/async-closures/return-type-mismatch.rs create mode 100644 tests/ui/async-await/async-closures/return-type-mismatch.stderr create mode 100644 tests/ui/async-await/async-closures/wrong-fn-kind.rs create mode 100644 tests/ui/async-await/async-closures/wrong-fn-kind.stderr diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index d4e072976fa69..e8bdf283c4f4d 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -394,13 +394,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coroutine_captures_by_ref_ty, ); - let ty::Coroutine(_, args) = *self.typeck_results.borrow().expr_ty(body.value).kind() + let ty::Coroutine(_, coroutine_args) = + *self.typeck_results.borrow().expr_ty(body.value).kind() else { bug!(); }; self.demand_eqtype( span, - args.as_coroutine().kind_ty(), + coroutine_args.as_coroutine().kind_ty(), Ty::from_closure_kind(self.tcx, closure_kind), ); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 75aedd5cd22ca..dda68fd424430 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -371,9 +371,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - if let Some(closure_kind) = obligation.self_ty().skip_binder().to_opt_closure_kind() - && let Some(goal_kind) = - obligation.predicate.skip_binder().trait_ref.args.type_at(1).to_opt_closure_kind() + let self_ty = obligation.self_ty().skip_binder(); + let target_kind_ty = obligation.predicate.skip_binder().trait_ref.args.type_at(1); + + // `to_opt_closure_kind` is kind of ICEy when it sees non-int types. + if !(self_ty.is_integral() || self_ty.is_ty_var()) { + return; + } + if !(target_kind_ty.is_integral() || self_ty.is_ty_var()) { + return; + } + + if let Some(closure_kind) = self_ty.to_opt_closure_kind() + && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind() { if closure_kind.extends(goal_kind) { candidates.vec.push(AsyncFnKindHelperCandidate); diff --git a/tests/ui/async-await/async-closures/arg-mismatch.rs b/tests/ui/async-await/async-closures/arg-mismatch.rs new file mode 100644 index 0000000000000..650e13677bc95 --- /dev/null +++ b/tests/ui/async-await/async-closures/arg-mismatch.rs @@ -0,0 +1,15 @@ +// aux-build:block-on.rs +// edition:2021 + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let c = async |x| {}; + c(1i32).await; + c(2usize).await; + //~^ ERROR mismatched types + }); +} diff --git a/tests/ui/async-await/async-closures/arg-mismatch.stderr b/tests/ui/async-await/async-closures/arg-mismatch.stderr new file mode 100644 index 0000000000000..70853ae28156f --- /dev/null +++ b/tests/ui/async-await/async-closures/arg-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/arg-mismatch.rs:12:11 + | +LL | c(2usize).await; + | - ^^^^^^ expected `i32`, found `usize` + | | + | arguments to this function are incorrect + | +note: closure parameter defined here + --> $DIR/arg-mismatch.rs:10:24 + | +LL | let c = async |x| {}; + | ^ +help: change the type of the numeric literal from `usize` to `i32` + | +LL | c(2i32).await; + | ~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs new file mode 100644 index 0000000000000..4afc43fe6bd92 --- /dev/null +++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs @@ -0,0 +1,23 @@ +// aux-build:block-on.rs +// edition:2021 +// run-pass + +// FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. +// ignore-pass (test emits codegen-time warnings) + +#![feature(async_closure, async_fn_traits)] + +extern crate block_on; + +use std::ops::AsyncFnOnce; + +fn main() { + block_on::block_on(async { + let x = async || {}; + + async fn needs_async_fn_once(x: impl AsyncFnOnce()) { + x().await; + } + needs_async_fn_once(x).await; + }); +} diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr new file mode 100644 index 0000000000000..9ae4692f003ef --- /dev/null +++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr @@ -0,0 +1,2 @@ +WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()])>.See . +WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected *mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()]), found *mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()]).See . diff --git a/tests/ui/async-await/async-closures/auxiliary/block-on.rs b/tests/ui/async-await/async-closures/auxiliary/block-on.rs new file mode 100644 index 0000000000000..3c27548b865a7 --- /dev/null +++ b/tests/ui/async-await/async-closures/auxiliary/block-on.rs @@ -0,0 +1,20 @@ +// edition: 2021 + +#![feature(async_closure, noop_waker, async_fn_traits)] + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + // Poll loop, just to test the future... + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match unsafe { fut.as_mut().poll(ctx) } { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} diff --git a/tests/ui/async-await/async-closures/await-inference-guidance.rs b/tests/ui/async-await/async-closures/await-inference-guidance.rs new file mode 100644 index 0000000000000..3702915cbadd1 --- /dev/null +++ b/tests/ui/async-await/async-closures/await-inference-guidance.rs @@ -0,0 +1,16 @@ +// aux-build:block-on.rs +// edition:2021 +// run-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let x = async |x: &str| -> String { x.to_owned() }; + let mut s = x("hello, world").await; + s.truncate(4); + println!("{s}"); + }); +} diff --git a/tests/ui/async-await/async-closures/brand.rs b/tests/ui/async-await/async-closures/brand.rs new file mode 100644 index 0000000000000..3bda7737bb406 --- /dev/null +++ b/tests/ui/async-await/async-closures/brand.rs @@ -0,0 +1,26 @@ +// aux-build:block-on.rs +// edition:2021 +// build-pass + +#![feature(async_closure, async_fn_traits)] + +extern crate block_on; + +use std::future::Future; +use std::marker::PhantomData; +use std::ops::AsyncFn; + +struct S; +struct B<'b>(PhantomData<&'b mut &'b mut ()>); + +impl S { + async fn q)>(self, f: F) { + f(B(PhantomData)).await; + } +} + +fn main() { + block_on::block_on(async { + S.q(async |b: B<'_>| { println!("...") }).await; + }); +} diff --git a/tests/ui/async-await/async-closures/higher-ranked-return.rs b/tests/ui/async-await/async-closures/higher-ranked-return.rs new file mode 100644 index 0000000000000..d98779c6ea320 --- /dev/null +++ b/tests/ui/async-await/async-closures/higher-ranked-return.rs @@ -0,0 +1,18 @@ +// aux-build:block-on.rs +// edition:2021 + +// known-bug: unknown +// Borrow checking doesn't like that higher-ranked output... + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let x = async move |x: &str| -> &str { + x + }; + let s = x("hello!").await; + }); +} diff --git a/tests/ui/async-await/async-closures/higher-ranked-return.stderr b/tests/ui/async-await/async-closures/higher-ranked-return.stderr new file mode 100644 index 0000000000000..268631f67cddf --- /dev/null +++ b/tests/ui/async-await/async-closures/higher-ranked-return.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/higher-ranked-return.rs:13:46 + | +LL | let x = async move |x: &str| -> &str { + | ________________________________-________----_^ + | | | | + | | | return type of async closure `{async closure body@$DIR/higher-ranked-return.rs:13:46: 15:10}` contains a lifetime `'2` + | | let's call the lifetime of this reference `'1` +LL | | x +LL | | }; + | |_________^ returning this value requires that `'1` must outlive `'2` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/async-closures/higher-ranked.rs b/tests/ui/async-await/async-closures/higher-ranked.rs index 5bbcc7041a8f8..17b5116cceb02 100644 --- a/tests/ui/async-await/async-closures/higher-ranked.rs +++ b/tests/ui/async-await/async-closures/higher-ranked.rs @@ -1,10 +1,16 @@ +// aux-build:block-on.rs // edition:2021 -// check-pass +// build-pass #![feature(async_closure)] +extern crate block_on; + fn main() { - let x = async move |x: &str| { - println!("{x}"); - }; + block_on::block_on(async { + let x = async move |x: &str| { + println!("{x}"); + }; + x("hello!").await; + }); } diff --git a/tests/ui/async-await/async-closures/is-not-fn.rs b/tests/ui/async-await/async-closures/is-not-fn.rs new file mode 100644 index 0000000000000..94c8e8563bd9e --- /dev/null +++ b/tests/ui/async-await/async-closures/is-not-fn.rs @@ -0,0 +1,12 @@ +// edition:2021 + +#![feature(async_closure)] + +fn main() { + fn needs_fn(x: impl FnOnce()) {} + needs_fn(async || {}); + //~^ ERROR expected a `FnOnce()` closure, found `{coroutine-closure@ + // FIXME(async_closures): This should explain in more detail how async fns don't + // implement the regular `Fn` traits. Or maybe we should just fix it and make them + // when there are no upvars or whatever. +} diff --git a/tests/ui/async-await/async-closures/is-not-fn.stderr b/tests/ui/async-await/async-closures/is-not-fn.stderr new file mode 100644 index 0000000000000..12da4b1fc6fb7 --- /dev/null +++ b/tests/ui/async-await/async-closures/is-not-fn.stderr @@ -0,0 +1,19 @@ +error[E0277]: expected a `FnOnce()` closure, found `{coroutine-closure@$DIR/is-not-fn.rs:7:14: 7:22}` + --> $DIR/is-not-fn.rs:7:14 + | +LL | needs_fn(async || {}); + | -------- ^^^^^^^^^^^ expected an `FnOnce()` closure, found `{coroutine-closure@$DIR/is-not-fn.rs:7:14: 7:22}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for `{coroutine-closure@$DIR/is-not-fn.rs:7:14: 7:22}` + = note: wrap the `{coroutine-closure@$DIR/is-not-fn.rs:7:14: 7:22}` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `needs_fn` + --> $DIR/is-not-fn.rs:6:25 + | +LL | fn needs_fn(x: impl FnOnce()) {} + | ^^^^^^^^ required by this bound in `needs_fn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-closures/move-consuming-capture.rs b/tests/ui/async-await/async-closures/move-consuming-capture.rs new file mode 100644 index 0000000000000..b8964c571f92e --- /dev/null +++ b/tests/ui/async-await/async-closures/move-consuming-capture.rs @@ -0,0 +1,20 @@ +// aux-build:block-on.rs +// edition:2021 + +#![feature(async_closure)] + +extern crate block_on; + +struct NoCopy; + +fn main() { + block_on::block_on(async { + let s = NoCopy; + let x = async move || { + drop(s); + }; + x().await; + x().await; + //~^ ERROR use of moved value: `x` + }); +} diff --git a/tests/ui/async-await/async-closures/move-consuming-capture.stderr b/tests/ui/async-await/async-closures/move-consuming-capture.stderr new file mode 100644 index 0000000000000..2c2a0d1162d17 --- /dev/null +++ b/tests/ui/async-await/async-closures/move-consuming-capture.stderr @@ -0,0 +1,17 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-consuming-capture.rs:17:9 + | +LL | let x = async move || { + | - move occurs because `x` has type `{coroutine-closure@$DIR/move-consuming-capture.rs:13:17: 13:30}`, which does not implement the `Copy` trait +... +LL | x().await; + | --- `x` moved due to this method call +LL | x().await; + | ^ value used here after move + | +note: `async_call_once` takes ownership of the receiver `self`, which moves `x` + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/async-closures/move-is-async-fn.rs b/tests/ui/async-await/async-closures/move-is-async-fn.rs new file mode 100644 index 0000000000000..943c062954185 --- /dev/null +++ b/tests/ui/async-await/async-closures/move-is-async-fn.rs @@ -0,0 +1,21 @@ +// aux-build:block-on.rs +// edition:2021 +// build-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let s = String::from("hello, world"); + let c = async move || { + println!("{s}"); + }; + c().await; + c().await; + + fn is_static(_: T) {} + is_static(c); + }); +} diff --git a/tests/ui/async-await/async-closures/mutate.rs b/tests/ui/async-await/async-closures/mutate.rs new file mode 100644 index 0000000000000..cc1df5f034ff0 --- /dev/null +++ b/tests/ui/async-await/async-closures/mutate.rs @@ -0,0 +1,19 @@ +// aux-build:block-on.rs +// edition:2021 +// run-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let mut prefix = String::from("Hello"); + let mut c = async move |x: &str| { + prefix.push(','); + println!("{prefix} {x}!") + }; + c("world").await; + c("rust").await; + }); +} diff --git a/tests/ui/async-await/async-closures/not-lending.rs b/tests/ui/async-await/async-closures/not-lending.rs new file mode 100644 index 0000000000000..90832e1a0745d --- /dev/null +++ b/tests/ui/async-await/async-closures/not-lending.rs @@ -0,0 +1,21 @@ +// aux-build:block-on.rs +// edition:2021 + +#![feature(async_closure)] + +extern crate block_on; + +// Make sure that we can't make an async closure that evaluates to a self-borrow. +// i.e. that the generator may reference captures, but the future's return type can't. + +fn main() { + block_on::block_on(async { + let s = String::new(); + let x = async move || -> &String { &s }; + //~^ ERROR lifetime may not live long enough + + let s = String::new(); + let x = async move || { &s }; + //~^ ERROR lifetime may not live long enough + }); +} diff --git a/tests/ui/async-await/async-closures/not-lending.stderr b/tests/ui/async-await/async-closures/not-lending.stderr new file mode 100644 index 0000000000000..1713e49b551e6 --- /dev/null +++ b/tests/ui/async-await/async-closures/not-lending.stderr @@ -0,0 +1,24 @@ +error: lifetime may not live long enough + --> $DIR/not-lending.rs:14:42 + | +LL | let x = async move || -> &String { &s }; + | ------------------------ ^^^^^^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of async closure `{async closure body@$DIR/not-lending.rs:14:42: 14:48}` contains a lifetime `'2` + | lifetime `'1` represents this closure's body + | + = note: closure implements `Fn`, so references to captured variables can't escape the closure + +error: lifetime may not live long enough + --> $DIR/not-lending.rs:18:31 + | +LL | let x = async move || { &s }; + | ------------- ^^^^^^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of async closure `{async closure body@$DIR/not-lending.rs:18:31: 18:37}` contains a lifetime `'2` + | lifetime `'1` represents this closure's body + | + = note: closure implements `Fn`, so references to captured variables can't escape the closure + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/async-closures/return-type-mismatch.rs b/tests/ui/async-await/async-closures/return-type-mismatch.rs new file mode 100644 index 0000000000000..9ad6be0b6e61e --- /dev/null +++ b/tests/ui/async-await/async-closures/return-type-mismatch.rs @@ -0,0 +1,14 @@ +// aux-build:block-on.rs +// edition:2021 + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let x = async || -> i32 { 0 }; + let y: usize = x().await; + //~^ ERROR mismatched types + }); +} diff --git a/tests/ui/async-await/async-closures/return-type-mismatch.stderr b/tests/ui/async-await/async-closures/return-type-mismatch.stderr new file mode 100644 index 0000000000000..53841f62777e6 --- /dev/null +++ b/tests/ui/async-await/async-closures/return-type-mismatch.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/return-type-mismatch.rs:11:24 + | +LL | let y: usize = x().await; + | ^^^^^^^^^ expected `usize`, found `i32` + | +help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit + | +LL | let y: usize = x().await.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs new file mode 100644 index 0000000000000..248288325319e --- /dev/null +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs @@ -0,0 +1,18 @@ +// edition:2021 + +// FIXME(async_closures): This needs a better error message! + +#![feature(async_closure, async_fn_traits)] + +use std::ops::AsyncFn; + +fn main() { + fn needs_async_fn(_: impl AsyncFn()) {} + + let mut x = 1; + needs_async_fn(async || { + //~^ ERROR i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper + // FIXME: Should say "closure is AsyncFnMut but it needs AsyncFn" or sth. + x += 1; + }); +} diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr new file mode 100644 index 0000000000000..ef95e6a211c74 --- /dev/null +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper` is not satisfied + --> $DIR/wrong-fn-kind.rs:13:20 + | +LL | needs_async_fn(async || { + | _____--------------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | // FIXME: Should say "closure is AsyncFnMut but it needs AsyncFn" or sth. +LL | | x += 1; +LL | | }); + | |_____^ the trait `ops::async_function::internal_implementation_detail::AsyncFnKindHelper` is not implemented for `i16` + | +note: required by a bound in `needs_async_fn` + --> $DIR/wrong-fn-kind.rs:10:31 + | +LL | fn needs_async_fn(_: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `needs_async_fn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From c98d6994a390044410c55c45195d330e4c8cd3d7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 25 Jan 2024 19:17:21 +0000 Subject: [PATCH 591/676] More comments, final tweaks --- compiler/rustc_ast_lowering/src/expr.rs | 3 ++ .../src/type_check/input_output.rs | 8 +++- .../rustc_borrowck/src/universal_regions.rs | 8 ++++ compiler/rustc_hir_analysis/src/collect.rs | 11 +---- compiler/rustc_hir_typeck/src/callee.rs | 9 ++++ compiler/rustc_hir_typeck/src/closure.rs | 39 +++++++++++----- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 10 ++++- compiler/rustc_middle/src/ty/flags.rs | 6 +-- compiler/rustc_middle/src/ty/instance.rs | 7 +++ compiler/rustc_middle/src/ty/sty.rs | 44 ++++++++++++++++--- .../rustc_mir_dataflow/src/value_analysis.rs | 3 ++ .../src/coroutine/by_move_body.rs | 13 +++++- .../src/solve/assembly/structural_traits.rs | 24 +++++++--- .../src/traits/project.rs | 3 ++ .../src/traits/select/candidate_assembly.rs | 4 ++ .../src/traits/select/confirmation.rs | 2 + .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_ty_utils/src/abi.rs | 6 +++ compiler/rustc_ty_utils/src/instance.rs | 7 +++ 20 files changed, 169 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 9990d526bf732..337dd55541ac6 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1074,6 +1074,9 @@ impl<'hir> LoweringContext<'_, 'hir> { body, fn_decl_span: self.lower_span(fn_decl_span), fn_arg_span: Some(self.lower_span(fn_arg_span)), + // Lower this as a `CoroutineClosure`. That will ensure that HIR typeck + // knows that a `FnDecl` output type like `-> &str` actually means + // "coroutine that returns &str", rather than directly returning a `&str`. kind: hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async), constness: hir::Constness::NotConst, }); diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 46fd0ce2b39a0..a5a7ce4ea3e86 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -61,6 +61,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { )), "this needs to be modified if we're lowering non-async closures" ); + // Make sure to use the args from `DefiningTy` so the right NLL region vids are prepopulated + // into the type. let args = args.as_coroutine_closure(); let tupled_upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( self.tcx(), @@ -87,11 +89,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty::CoroutineArgsParts { parent_args: args.parent_args(), kind_ty: Ty::from_closure_kind(self.tcx(), args.kind()), + return_ty: user_provided_sig.output(), + tupled_upvars_ty, + // For async closures, none of these can be annotated, so just fill + // them with fresh ty vars. resume_ty: next_ty_var(), yield_ty: next_ty_var(), witness: next_ty_var(), - return_ty: user_provided_sig.output(), - tupled_upvars_ty: tupled_upvars_ty, }, ) .args, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index d696e624823af..111eaaf60f7b2 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -720,6 +720,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { ty::Binder::dummy(inputs_and_output) } + // Construct the signature of the CoroutineClosure for the purposes of borrowck. + // This is pretty straightforward -- we: + // 1. first grab the `coroutine_closure_sig`, + // 2. compute the self type (`&`/`&mut`/no borrow), + // 3. flatten the tupled_input_tys, + // 4. construct the correct generator type to return with + // `CoroutineClosureSignature::to_coroutine_given_kind_and_upvars`. + // Then we wrap it all up into a list of inputs and output. DefiningTy::CoroutineClosure(def_id, args) => { assert_eq!(self.mir_def.to_def_id(), def_id); let closure_sig = args.as_coroutine_closure().coroutine_closure_sig(); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8fdd3cfe3cf88..fbcebb7c87c9b 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1533,15 +1533,8 @@ fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option, def_id: LocalDefId) -> DefId { - let Node::Expr(&hir::Expr { - kind: - hir::ExprKind::Closure(&rustc_hir::Closure { - kind: hir::ClosureKind::CoroutineClosure(_), - body, - .. - }), - .. - }) = tcx.hir_node_by_def_id(def_id) + let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } = + tcx.hir_node_by_def_id(def_id).expect_closure() else { bug!() }; diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 730a475f63049..fbe6f454dbc92 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -166,6 +166,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Some(CallStep::DeferredClosure(def_id, closure_sig)); } + // When calling a `CoroutineClosure` that is local to the body, we will + // not know what its `closure_kind` is yet. Instead, just fill in the + // signature with an infer var for the `tupled_upvars_ty` of the coroutine, + // and record a deferred call resolution which will constrain that var + // as part of `AsyncFn*` trait confirmation. ty::CoroutineClosure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { let def_id = def_id.expect_local(); let closure_args = args.as_coroutine_closure(); @@ -183,6 +188,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coroutine_closure_sig.to_coroutine( self.tcx, closure_args.parent_args(), + // Inherit the kind ty of the closure, since we're calling this + // coroutine with the most relaxed `AsyncFn*` trait that we can. + // We don't necessarily need to do this here, but it saves us + // computing one more infer var that will get constrained later. closure_args.kind_ty(), self.tcx.coroutine_for_closure(def_id), tupled_upvars_ty, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 014293c1f8325..a985fa201d071 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -175,6 +175,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { interior, )); + // Coroutines that come from coroutine closures have not yet determined + // their kind ty, so make a fresh infer var which will be constrained + // later during upvar analysis. Regular coroutines always have the kind + // ty of `().` let kind_ty = match kind { hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) => self .next_ty_var(TypeVariableOrigin { @@ -203,6 +207,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } hir::ClosureKind::CoroutineClosure(kind) => { + // async closures always return the type ascribed after the `->` (if present), + // and yield `()`. let (bound_return_ty, bound_yield_ty) = match kind { hir::CoroutineDesugaring::Async => { (bound_sig.skip_binder().output(), tcx.types.unit) @@ -211,6 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { todo!("`gen` and `async gen` closures not supported yet") } }; + // Compute all of the variables that will be used to populate the coroutine. let resume_ty = self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, @@ -258,20 +265,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, }); + + // We need to turn the liberated signature that we got from HIR, which + // looks something like `|Args...| -> T`, into a signature that is suitable + // for type checking the inner body of the closure, which always returns a + // coroutine. To do so, we use the `CoroutineClosureSignature` to compute + // the coroutine type, filling in the tupled_upvars_ty and kind_ty with infer + // vars which will get constrained during upvar analysis. + let coroutine_output_ty = tcx.liberate_late_bound_regions( + expr_def_id.to_def_id(), + closure_args.coroutine_closure_sig().map_bound(|sig| { + sig.to_coroutine( + tcx, + parent_args, + closure_kind_ty, + tcx.coroutine_for_closure(expr_def_id), + coroutine_upvars_ty, + ) + }), + ); liberated_sig = tcx.mk_fn_sig( liberated_sig.inputs().iter().copied(), - tcx.liberate_late_bound_regions( - expr_def_id.to_def_id(), - closure_args.coroutine_closure_sig().map_bound(|sig| { - sig.to_coroutine( - tcx, - parent_args, - closure_kind_ty, - tcx.coroutine_for_closure(expr_def_id), - coroutine_upvars_ty, - ) - }), - ), + coroutine_output_ty, liberated_sig.c_variadic, liberated_sig.unsafety, liberated_sig.abi, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 23fb7eba65606..d30c7a4fb3899 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -335,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } - // For this check, we do *not* want to treat async coroutine-closures (async blocks) + // For this check, we do *not* want to treat async coroutine closures (async blocks) // as proper closures. Doing so would regress type inference when feeding // the return value of an argument-position async block to an argument-position // closure wrapped in a block. diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index e8bdf283c4f4d..c4773a885218a 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -336,6 +336,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + // For coroutine-closures, we additionally must compute the + // `coroutine_captures_by_ref_ty` type, which is used to generate the by-ref + // version of the coroutine-closure's output coroutine. if let UpvarArgs::CoroutineClosure(args) = args { let closure_env_region: ty::Region<'_> = ty::Region::new_bound( self.tcx, @@ -353,7 +356,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.coroutine_for_closure(closure_def_id).expect_local(), ) // Skip the captures that are just moving the closure's args - // into the coroutine. These are always by move. + // into the coroutine. These are always by move, and we append + // those later in the `CoroutineClosureSignature` helper functions. .skip( args.as_coroutine_closure() .coroutine_closure_sig() @@ -365,6 +369,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|captured_place| { let upvar_ty = captured_place.place.ty(); let capture = captured_place.info.capture_kind; + // Not all upvars are captured by ref, so use + // `apply_capture_kind_on_capture_ty` to ensure that we + // compute the right captured type. apply_capture_kind_on_capture_ty( self.tcx, upvar_ty, @@ -394,6 +401,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coroutine_captures_by_ref_ty, ); + // Additionally, we can now constrain the coroutine's kind type. let ty::Coroutine(_, coroutine_args) = *self.typeck_results.borrow().expr_ty(body.value).kind() else { diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index deb6e73ea7142..0f4b5fe228c96 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -145,11 +145,11 @@ impl FlagComputation { self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; } - self.add_ty(args.signature_parts_ty()); - self.add_ty(args.coroutine_witness_ty()); - self.add_ty(args.coroutine_captures_by_ref_ty()); self.add_ty(args.kind_ty()); + self.add_ty(args.signature_parts_ty()); self.add_ty(args.tupled_upvars_ty()); + self.add_ty(args.coroutine_captures_by_ref_ty()); + self.add_ty(args.coroutine_witness_ty()); } &ty::Bound(debruijn, _) => { diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 2c80dd021451f..1c9415ef3b093 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -646,9 +646,16 @@ impl<'tcx> Instance<'tcx> { bug!() }; + // If the closure's kind ty disagrees with the identity closure's kind ty, + // then this must be a coroutine generated by one of the `ConstructCoroutineInClosureShim`s. if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() { Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args }) } else { + assert_eq!( + args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(), + ty::ClosureKind::FnOnce, + "FIXME(async_closures): Generate a by-mut body here." + ); Some(Instance { def: ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id }, args, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 3bbebaddbdd33..927924452f913 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -275,6 +275,10 @@ pub struct CoroutineClosureArgs<'tcx> { pub args: GenericArgsRef<'tcx>, } +/// See docs for explanation of how each argument is used. +/// +/// See [`CoroutineClosureSignature`] for how these arguments are put together +/// to make a callable [`FnSig`] suitable for typeck and borrowck. pub struct CoroutineClosureArgsParts<'tcx> { /// This is the args of the typeck root. pub parent_args: &'tcx [GenericArg<'tcx>], @@ -409,17 +413,32 @@ pub struct CoroutineClosureSignature<'tcx> { pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, pub return_ty: Ty<'tcx>, + + // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types + // never actually differ. But we save them rather than recreating them + // from scratch just for good measure. + /// Always false pub c_variadic: bool, + /// Always [`hir::Unsafety::Normal`] pub unsafety: hir::Unsafety, + /// Always [`abi::Abi::RustCall`] pub abi: abi::Abi, } impl<'tcx> CoroutineClosureSignature<'tcx> { + /// Construct a coroutine from the closure signature. Since a coroutine signature + /// is agnostic to the type of generator that is returned (by-ref/by-move), + /// the caller must specify what "flavor" of generator that they'd like to + /// create. Additionally, they must manually compute the upvars of the closure. + /// + /// This helper is not really meant to be used directly except for early on + /// during typeck, when we want to put inference vars into the kind and upvars tys. + /// When the kind and upvars are known, use the other helper functions. pub fn to_coroutine( self, tcx: TyCtxt<'tcx>, parent_args: &'tcx [GenericArg<'tcx>], - kind_ty: Ty<'tcx>, + coroutine_kind_ty: Ty<'tcx>, coroutine_def_id: DefId, tupled_upvars_ty: Ty<'tcx>, ) -> Ty<'tcx> { @@ -427,7 +446,7 @@ impl<'tcx> CoroutineClosureSignature<'tcx> { tcx, ty::CoroutineArgsParts { parent_args, - kind_ty, + kind_ty: coroutine_kind_ty, resume_ty: self.resume_ty, yield_ty: self.yield_ty, return_ty: self.return_ty, @@ -439,19 +458,24 @@ impl<'tcx> CoroutineClosureSignature<'tcx> { Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args) } + /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine + /// returned by that corresponding async fn trait. + /// + /// This function expects the upvars to have been computed already, and doesn't check + /// that the `ClosureKind` is actually supported by the coroutine-closure. pub fn to_coroutine_given_kind_and_upvars( self, tcx: TyCtxt<'tcx>, parent_args: &'tcx [GenericArg<'tcx>], coroutine_def_id: DefId, - closure_kind: ty::ClosureKind, + goal_kind: ty::ClosureKind, env_region: ty::Region<'tcx>, closure_tupled_upvars_ty: Ty<'tcx>, coroutine_captures_by_ref_ty: Ty<'tcx>, ) -> Ty<'tcx> { let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind( tcx, - closure_kind, + goal_kind, self.tupled_inputs_ty, closure_tupled_upvars_ty, coroutine_captures_by_ref_ty, @@ -461,13 +485,21 @@ impl<'tcx> CoroutineClosureSignature<'tcx> { self.to_coroutine( tcx, parent_args, - Ty::from_closure_kind(tcx, closure_kind), + Ty::from_closure_kind(tcx, goal_kind), coroutine_def_id, tupled_upvars_ty, ) } - /// Given a closure kind, compute the tupled upvars that the given coroutine would return. + /// Compute the tupled upvars that a coroutine-closure's output coroutine + /// would return for the given `ClosureKind`. + /// + /// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref" + /// to return a set of upvars which are borrowed with the given `env_region`. + /// + /// This ensures that the `AsyncFn::call` will return a coroutine whose upvars' + /// lifetimes are related to the lifetime of the borrow on the closure made for + /// the call. This allows borrowck to enforce the self-borrows correctly. pub fn tupled_upvars_by_closure_kind( tcx: TyCtxt<'tcx>, kind: ty::ClosureKind, diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index a85e53ff241d5..2b2af6ee7da3e 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -1149,6 +1149,9 @@ pub fn iter_fields<'tcx>( ty::Closure(_, args) => { iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f); } + ty::Coroutine(_, args) => { + iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, param_env, f); + } ty::CoroutineClosure(_, args) => { iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, param_env, f); } diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 4e3e70bdafef1..1cc0a5026d14d 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -1,3 +1,8 @@ +//! A MIR pass which duplicates a coroutine's body and removes any derefs which +//! would be present for upvars that are taken by-ref. The result of which will +//! be a coroutine body that takes all of its upvars by-move, and which we stash +//! into the `CoroutineInfo` for all coroutines returned by coroutine-closures. + use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_middle::mir::visit::MutVisitor; @@ -87,11 +92,16 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> { && self.by_ref_fields.contains(&idx) { let (begin, end) = place.projection[1..].split_first().unwrap(); + // FIXME(async_closures): I'm actually a bit surprised to see that we always + // initially deref the by-ref upvars. If this is not actually true, then we + // will at least get an ICE that explains why this isn't true :^) assert_eq!(*begin, mir::ProjectionElem::Deref); + // Peel one ref off of the ty. + let peeled_ty = ty.builtin_deref(true).unwrap().ty; *place = mir::Place { local: place.local, projection: self.tcx.mk_place_elems_from_iter( - [mir::ProjectionElem::Field(idx, ty.builtin_deref(true).unwrap().ty)] + [mir::ProjectionElem::Field(idx, peeled_ty)] .into_iter() .chain(end.iter().copied()), ), @@ -101,6 +111,7 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> { } fn visit_local_decl(&mut self, local: mir::Local, local_decl: &mut mir::LocalDecl<'tcx>) { + // Replace the type of the self arg. if local == ty::CAPTURE_STRUCT_LOCAL { local_decl.ty = self.by_move_coroutine_ty; } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index dbf3e4876a960..d02578c484649 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -309,14 +309,19 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( } // Returns a binder of the tupled inputs types, output type, and coroutine type -// from a builtin async closure type. +// from a builtin coroutine-closure type. If we don't yet know the closure kind of +// the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper` +// which enforces the closure is actually callable with the given trait. When we +// know the kind already, we can short-circuit this check. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tcx>( tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>, goal_kind: ty::ClosureKind, env_region: ty::Region<'tcx>, -) -> Result<(ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Vec>), NoSolution> -{ +) -> Result< + (ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Option>), + NoSolution, +> { match *self_ty.kind() { ty::CoroutineClosure(def_id, args) => { let args = args.as_coroutine_closure(); @@ -339,7 +344,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc ); (sig.tupled_inputs_ty, sig.return_ty, coroutine_ty) }), - vec![], + None, )) } else { let async_fn_kind_trait_def_id = @@ -350,6 +355,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc .next() .unwrap() .def_id; + // When we don't know the closure kind (and therefore also the closure's upvars, + // which are computed at the same time), we must delay the computation of the + // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait + // goal functions similarly to the old `ClosureKind` predicate, and ensures that + // the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars` + // will project to the right upvars for the generator, appending the inputs and + // coroutine upvars respecting the closure kind. Ok(( args.coroutine_closure_sig().map_bound(|sig| { let tupled_upvars_ty = Ty::new_projection( @@ -373,14 +385,14 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc ); (sig.tupled_inputs_ty, sig.return_ty, coroutine_ty) }), - vec![ + Some( ty::TraitRef::new( tcx, async_fn_kind_trait_def_id, [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], ) .to_predicate(tcx), - ], + ), )) } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index a8d6b9812be3a..955c81eee6be3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2491,6 +2491,9 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( // since all this does is make the solver do more work. // // The code duplication due to the different length args is kind of weird, too. + // + // See the logic in `structural_traits` in the new solver to understand a bit + // more clearly how this *should* look. let poly_cache_entry = args.coroutine_closure_sig().map_bound(|sig| { let (projection_ty, term) = match tcx.item_name(obligation.predicate.def_id) { sym::CallOnceFuture => { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index dda68fd424430..2258e7961038b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -121,9 +121,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates); } + // FIXME: Put these into `else if` blocks above, since they're built-in. self.assemble_closure_candidates(obligation, &mut candidates); self.assemble_async_closure_candidates(obligation, &mut candidates); self.assemble_fn_pointer_candidates(obligation, &mut candidates); + self.assemble_candidates_from_impls(obligation, &mut candidates); self.assemble_candidates_from_object_ty(obligation, &mut candidates); } @@ -382,6 +384,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } + // Check that the self kind extends the goal kind. If it does, + // then there's nothing else to check. if let Some(closure_kind) = self_ty.to_opt_closure_kind() && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind() { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 79336a9d4e8f0..c9d06b0f67521 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -88,6 +88,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure) } + // No nested obligations or confirmation process. The checks that we do in + // candidate assembly are sufficient. AsyncFnKindHelperCandidate => ImplSource::Builtin(BuiltinImplSource::Misc, vec![]), CoroutineCandidate => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 88584a61b13de..b4f13ee95a652 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -728,7 +728,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } ty::CoroutineClosure(did, args) => { - // See the above comments. + // See the above comments. The same apply to coroutine-closures. walker.skip_current_subtree(); self.compute(args.as_coroutine_closure().tupled_upvars_ty().into()); let obligations = self.nominal_obligations(did, args); diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 3ea48ee824d47..e023283a70957 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -112,6 +112,10 @@ fn fn_sig_for_fn_abi<'tcx>( }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); + // When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`, + // make sure we respect the `target_kind` in that shim. + // FIXME(async_closures): This shouldn't be needed, and we should be populating + // a separate def-id for these bodies. let mut kind = args.as_coroutine_closure().kind(); if let InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. } = instance.def { kind = target_kind; @@ -141,6 +145,8 @@ fn fn_sig_for_fn_abi<'tcx>( ) } ty::Coroutine(did, args) => { + // FIXME(async_closures): This isn't right for `CoroutineByMoveShim`. + let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let sig = args.as_coroutine().sig(); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index fc224d242db6d..9faad10dd14df 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -287,6 +287,13 @@ fn resolve_associated_item<'tcx>( { match *rcvr_args.type_at(0).kind() { ty::CoroutineClosure(coroutine_closure_def_id, args) => { + // If we're computing `AsyncFnOnce`/`AsyncFnMut` for a by-ref closure, + // or `AsyncFnOnce` for a by-mut closure, then construct a new body that + // has the right return types. + // + // Specifically, `AsyncFnMut` for a by-ref coroutine-closure just needs + // to have its input and output types fixed (`&mut self` and returning + // `i16` coroutine kind). if target_kind > args.as_coroutine_closure().kind() { Some(Instance { def: ty::InstanceDef::ConstructCoroutineInClosureShim { From ca444160232a1bf1914da906da9e061a7636955c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 29 Jan 2024 17:41:51 +0000 Subject: [PATCH 592/676] Fix drop shim for AsyncFnOnce closure, AsyncFnMut shim for AsyncFn closure --- .../src/interpret/terminator.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 18 ++++- compiler/rustc_middle/src/mir/mono.rs | 2 +- compiler/rustc_middle/src/mir/visit.rs | 2 +- compiler/rustc_middle/src/ty/instance.rs | 26 +++---- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/mod.rs | 21 ++++- .../src/coroutine/by_move_body.rs | 45 ++++++++++- compiler/rustc_mir_transform/src/inline.rs | 2 +- .../rustc_mir_transform/src/inline/cycle.rs | 2 +- .../rustc_mir_transform/src/pass_manager.rs | 11 ++- compiler/rustc_mir_transform/src/shim.rs | 77 +++++++++++++++---- compiler/rustc_monomorphize/src/collector.rs | 2 +- .../rustc_monomorphize/src/partitioning.rs | 4 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 2 +- compiler/rustc_symbol_mangling/src/legacy.rs | 33 +++++--- compiler/rustc_symbol_mangling/src/v0.rs | 7 ++ compiler/rustc_ty_utils/src/abi.rs | 2 +- ...ure#0}.coroutine_by_move.0.panic-abort.mir | 47 +++++++++++ ...re#0}.coroutine_by_move.0.panic-unwind.mir | 47 +++++++++++ ...sure#0}.coroutine_by_mut.0.panic-abort.mir | 47 +++++++++++ ...ure#0}.coroutine_by_mut.0.panic-unwind.mir | 47 +++++++++++ ...oroutine_closure_by_move.0.panic-abort.mir | 10 +++ ...routine_closure_by_move.0.panic-unwind.mir | 10 +++ ...coroutine_closure_by_mut.0.panic-abort.mir | 16 ++++ ...oroutine_closure_by_mut.0.panic-unwind.mir | 16 ++++ tests/mir-opt/async_closure_shims.rs | 46 +++++++++++ .../async-fn-mut-for-async-fn.rs | 23 ++++++ .../async-fn-mut-for-async-fn.stderr | 1 + .../async-fn-once-for-async-fn.stderr | 3 +- .../ui/async-await/async-closures/def-path.rs | 4 +- .../async-closures/def-path.stderr | 4 +- tests/ui/async-await/async-closures/drop.rs | 40 ++++++++++ .../async-closures/drop.run.stdout | 5 ++ tests/ui/async-await/async-closures/mangle.rs | 36 +++++++++ 35 files changed, 595 insertions(+), 67 deletions(-) create mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir create mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir create mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-abort.mir create mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-unwind.mir create mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir create mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir create mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir create mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir create mode 100644 tests/mir-opt/async_closure_shims.rs create mode 100644 tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs create mode 100644 tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr create mode 100644 tests/ui/async-await/async-closures/drop.rs create mode 100644 tests/ui/async-await/async-closures/drop.run.stdout create mode 100644 tests/ui/async-await/async-closures/mangle.rs diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index b8d6836da14a8..85a2e4778d252 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -546,7 +546,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineByMoveShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 3d6c28088ad59..9475b89aa15c2 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -265,7 +265,7 @@ pub struct CoroutineInfo<'tcx> { /// The body of the coroutine, modified to take its upvars by move rather than by ref. /// /// This is used by coroutine-closures, which must return a different flavor of coroutine - /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` which + /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which /// is run right after building the initial MIR, and will only be populated for coroutines /// which come out of the async closure desugaring. /// @@ -274,6 +274,13 @@ pub struct CoroutineInfo<'tcx> { /// using `run_passes`. pub by_move_body: Option>, + /// The body of the coroutine, modified to take its upvars by mutable ref rather than by + /// immutable ref. + /// + /// FIXME(async_closures): This is literally the same body as the parent body. Find a better + /// way to represent the by-mut signature (or cap the closure-kind of the coroutine). + pub by_mut_body: Option>, + /// The layout of a coroutine. This field is populated after the state transform pass. pub coroutine_layout: Option>, @@ -294,6 +301,7 @@ impl<'tcx> CoroutineInfo<'tcx> { yield_ty: Some(yield_ty), resume_ty: Some(resume_ty), by_move_body: None, + by_mut_body: None, coroutine_drop: None, coroutine_layout: None, } @@ -604,6 +612,14 @@ impl<'tcx> Body<'tcx> { self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_drop.as_ref()) } + pub fn coroutine_by_move_body(&self) -> Option<&Body<'tcx>> { + self.coroutine.as_ref()?.by_move_body.as_ref() + } + + pub fn coroutine_by_mut_body(&self) -> Option<&Body<'tcx>> { + self.coroutine.as_ref()?.by_mut_body.as_ref() + } + #[inline] pub fn coroutine_kind(&self) -> Option { self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index e6d1535fdf2f6..6937df7bb1897 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -403,7 +403,7 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceDef::Virtual(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineByMoveShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index ce1859d6adae3..2c5ca82a4cd39 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -346,7 +346,7 @@ macro_rules! make_mir_visitor { ty::InstanceDef::ThreadLocalShim(_def_id) | ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } | ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, target_kind: _ } | - ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id: _def_id } | + ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id, target_kind: _ } | ty::InstanceDef::DropGlue(_def_id, None) => {} ty::InstanceDef::FnPtrShim(_def_id, ty) | diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 1c9415ef3b093..9c1f4b20d2c83 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -102,10 +102,12 @@ pub enum InstanceDef<'tcx> { }, /// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce` - /// is called on a coroutine-closure whose closure kind is not `FnOnce`. This - /// will select the body that is produced by the `ByMoveBody` transform, and thus + /// is called on a coroutine-closure whose closure kind greater than `FnOnce`, or + /// similarly for `AsyncFnMut`. + /// + /// This will select the body that is produced by the `ByMoveBody` transform, and thus /// take and use all of its upvars by-move rather than by-ref. - CoroutineByMoveShim { coroutine_def_id: DefId }, + CoroutineKindShim { coroutine_def_id: DefId, target_kind: ty::ClosureKind }, /// Compiler-generated accessor for thread locals which returns a reference to the thread local /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking @@ -192,7 +194,7 @@ impl<'tcx> InstanceDef<'tcx> { coroutine_closure_def_id: def_id, target_kind: _, } - | ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id: def_id } + | ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id, target_kind: _ } | InstanceDef::DropGlue(def_id, _) | InstanceDef::CloneShim(def_id, _) | InstanceDef::FnPtrAddrShim(def_id, _) => def_id, @@ -213,7 +215,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineByMoveShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => None, @@ -310,7 +312,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::DropGlue(_, Some(_)) => false, InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineByMoveShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::Item(_) | InstanceDef::Intrinsic(..) @@ -349,7 +351,7 @@ fn fmt_instance( InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"), InstanceDef::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), - InstanceDef::CoroutineByMoveShim { .. } => write!(f, " - shim"), + InstanceDef::CoroutineKindShim { .. } => write!(f, " - shim"), InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"), InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"), @@ -651,13 +653,11 @@ impl<'tcx> Instance<'tcx> { if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() { Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args }) } else { - assert_eq!( - args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(), - ty::ClosureKind::FnOnce, - "FIXME(async_closures): Generate a by-mut body here." - ); Some(Instance { - def: ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id }, + def: ty::InstanceDef::CoroutineKindShim { + coroutine_def_id, + target_kind: args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(), + }, args, }) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9ceb3ec3f615c..c9137f374a238 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1681,7 +1681,7 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceDef::Virtual(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineByMoveShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) | ty::InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 7026d2af29853..19f8ba124f143 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -3,6 +3,7 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sso::SsoHashSet; +use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; @@ -130,8 +131,24 @@ pub trait Printer<'tcx>: Sized { parent_args = &args[..generics.parent_count.min(args.len())]; match key.disambiguated_data.data { - // Closures' own generics are only captures, don't print them. - DefPathData::Closure => {} + DefPathData::Closure => { + // FIXME(async_closures): This is somewhat ugly. + // We need to additionally print the `kind` field of a closure if + // it is desugared from a coroutine-closure. + if let Some(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Closure, + )) = self.tcx().coroutine_kind(def_id) + && args.len() >= parent_args.len() + 1 + { + return self.path_generic_args( + |cx| cx.print_def_path(def_id, parent_args), + &args[..parent_args.len() + 1][..1], + ); + } else { + // Closures' own generics are only captures, don't print them. + } + } // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`. // Anon consts doesn't have their own generics, and inline consts' own // generics are their inferred types, so don't print them. diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 1cc0a5026d14d..fcd4715b9e88c 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_middle::mir::visit::MutVisitor; -use rustc_middle::mir::{self, MirPass}; +use rustc_middle::mir::{self, dump_mir, MirPass}; use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt}; use rustc_target::abi::FieldIdx; @@ -24,7 +24,9 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { }; let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!() }; - if args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() == ty::ClosureKind::FnOnce { + + let coroutine_kind = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(); + if coroutine_kind == ty::ClosureKind::FnOnce { return; } @@ -58,14 +60,49 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { let mut by_move_body = body.clone(); MakeByMoveBody { tcx, by_ref_fields, by_move_coroutine_ty }.visit_body(&mut by_move_body); + dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); by_move_body.source = mir::MirSource { - instance: InstanceDef::CoroutineByMoveShim { + instance: InstanceDef::CoroutineKindShim { coroutine_def_id: coroutine_def_id.to_def_id(), + target_kind: ty::ClosureKind::FnOnce, }, promoted: None, }; - body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body); + + // If this is coming from an `AsyncFn` coroutine-closure, we must also create a by-mut body. + // This is actually just a copy of the by-ref body, but with a different self type. + // FIXME(async_closures): We could probably unify this with the by-ref body somehow. + if coroutine_kind == ty::ClosureKind::Fn { + let by_mut_coroutine_ty = Ty::new_coroutine( + tcx, + coroutine_def_id.to_def_id(), + ty::CoroutineArgs::new( + tcx, + ty::CoroutineArgsParts { + parent_args: args.as_coroutine().parent_args(), + kind_ty: Ty::from_closure_kind(tcx, ty::ClosureKind::FnMut), + resume_ty: args.as_coroutine().resume_ty(), + yield_ty: args.as_coroutine().yield_ty(), + return_ty: args.as_coroutine().return_ty(), + witness: args.as_coroutine().witness(), + tupled_upvars_ty: args.as_coroutine().tupled_upvars_ty(), + }, + ) + .args, + ); + let mut by_mut_body = body.clone(); + by_mut_body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty = by_mut_coroutine_ty; + dump_mir(tcx, false, "coroutine_by_mut", &0, &by_mut_body, |_, _| Ok(())); + by_mut_body.source = mir::MirSource { + instance: InstanceDef::CoroutineKindShim { + coroutine_def_id: coroutine_def_id.to_def_id(), + target_kind: ty::ClosureKind::FnMut, + }, + promoted: None, + }; + body.coroutine.as_mut().unwrap().by_mut_body = Some(by_mut_body); + } } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 24bc84a235c2d..e77553a03d672 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -318,7 +318,7 @@ impl<'tcx> Inliner<'tcx> { | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineByMoveShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 77ff780393efb..5b03bc361dd3c 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -88,7 +88,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineByMoveShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::ThreadLocalShim { .. } | InstanceDef::CloneShim(..) => {} diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index c7e770904fbb8..605e1ad46d775 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -190,10 +190,13 @@ fn run_passes_inner<'tcx>( body.pass_count = 1; } - if let Some(coroutine) = body.coroutine.as_mut() - && let Some(by_move_body) = coroutine.by_move_body.as_mut() - { - run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each); + if let Some(coroutine) = body.coroutine.as_mut() { + if let Some(by_move_body) = coroutine.by_move_body.as_mut() { + run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each); + } + if let Some(by_mut_body) = coroutine.by_mut_body.as_mut() { + run_passes_inner(tcx, by_mut_body, passes, phase_change, validate_each); + } } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 668ccdd873550..7b6de3a543955 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -72,32 +72,70 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' } => match target_kind { ty::ClosureKind::Fn => unreachable!("shouldn't be building shim for Fn"), ty::ClosureKind::FnMut => { - let body = build_construct_coroutine_by_mut_shim(tcx, coroutine_closure_def_id); - // No need to optimize the body, it has already been optimized. - return body; + // No need to optimize the body, it has already been optimized + // since we steal it from the `AsyncFn::call` body and just fix + // the return type. + return build_construct_coroutine_by_mut_shim(tcx, coroutine_closure_def_id); } ty::ClosureKind::FnOnce => { build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id) } }, - ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id } => { - return tcx - .optimized_mir(coroutine_def_id) - .coroutine - .as_ref() - .unwrap() - .by_move_body - .as_ref() - .unwrap() - .clone(); - } + ty::InstanceDef::CoroutineKindShim { coroutine_def_id, target_kind } => match target_kind { + ty::ClosureKind::Fn => unreachable!(), + ty::ClosureKind::FnMut => { + return tcx + .optimized_mir(coroutine_def_id) + .coroutine_by_mut_body() + .unwrap() + .clone(); + } + ty::ClosureKind::FnOnce => { + return tcx + .optimized_mir(coroutine_def_id) + .coroutine_by_move_body() + .unwrap() + .clone(); + } + }, ty::InstanceDef::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? if let Some(ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { - let body = tcx.optimized_mir(*coroutine_def_id).coroutine_drop().unwrap(); + let coroutine_body = tcx.optimized_mir(*coroutine_def_id); + + let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind() + else { + bug!() + }; + + // If this is a regular coroutine, grab its drop shim. If this is a coroutine + // that comes from a coroutine-closure, and the kind ty differs from the "maximum" + // kind that it supports, then grab the appropriate drop shim. This ensures that + // the future returned by `<[coroutine-closure] as AsyncFnOnce>::call_once` will + // drop the coroutine-closure's upvars. + let body = if id_args.as_coroutine().kind_ty() == args.as_coroutine().kind_ty() { + coroutine_body.coroutine_drop().unwrap() + } else { + match args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() { + ty::ClosureKind::Fn => { + unreachable!() + } + ty::ClosureKind::FnMut => coroutine_body + .coroutine_by_mut_body() + .unwrap() + .coroutine_drop() + .unwrap(), + ty::ClosureKind::FnOnce => coroutine_body + .coroutine_by_move_body() + .unwrap() + .coroutine_drop() + .unwrap(), + } + }; + let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); debug!("make_shim({:?}) = {:?}", instance, body); @@ -1076,7 +1114,11 @@ fn build_construct_coroutine_by_move_shim<'tcx>( target_kind: ty::ClosureKind::FnOnce, }); - new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span) + let body = + new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span); + dump_mir(tcx, false, "coroutine_closure_by_move", &0, &body, |_, _| Ok(())); + + body } fn build_construct_coroutine_by_mut_shim<'tcx>( @@ -1110,5 +1152,8 @@ fn build_construct_coroutine_by_mut_shim<'tcx>( target_kind: ty::ClosureKind::FnMut, }); + body.pass_count = 0; + dump_mir(tcx, false, "coroutine_closure_by_mut", &0, &body, |_, _| Ok(())); + body } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index cf3c8e1fdd3b4..3376af986531e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -984,7 +984,7 @@ fn visit_instance_use<'tcx>( | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineByMoveShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::Item(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 22b35c4344b86..4f6ea66df7be1 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -621,7 +621,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineByMoveShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::Virtual(..) @@ -786,7 +786,7 @@ fn mono_item_visibility<'tcx>( | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } - | InstanceDef::CoroutineByMoveShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 066348dcb67bc..959a17d24b7ce 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -800,7 +800,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceDef::FnPtrAddrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } - | ty::InstanceDef::CoroutineByMoveShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::ThreadLocalShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 5af9503087ab9..646649293fc76 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -64,16 +64,29 @@ pub(super) fn mangle<'tcx>( ) .unwrap(); - if let ty::InstanceDef::ThreadLocalShim(..) = instance.def { - let _ = printer.write_str("{{tls-shim}}"); - } - - if let ty::InstanceDef::VTableShim(..) = instance.def { - let _ = printer.write_str("{{vtable-shim}}"); - } - - if let ty::InstanceDef::ReifyShim(..) = instance.def { - let _ = printer.write_str("{{reify-shim}}"); + match instance.def { + ty::InstanceDef::ThreadLocalShim(..) => { + printer.write_str("{{tls-shim}}").unwrap(); + } + ty::InstanceDef::VTableShim(..) => { + printer.write_str("{{vtable-shim}}").unwrap(); + } + ty::InstanceDef::ReifyShim(..) => { + printer.write_str("{{reify-shim}}").unwrap(); + } + // FIXME(async_closures): This shouldn't be needed when we fix + // `Instance::ty`/`Instance::def_id`. + ty::InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. } + | ty::InstanceDef::CoroutineKindShim { target_kind, .. } => match target_kind { + ty::ClosureKind::Fn => unreachable!(), + ty::ClosureKind::FnMut => { + printer.write_str("{{fn-mut-shim}}").unwrap(); + } + ty::ClosureKind::FnOnce => { + printer.write_str("{{fn-once-shim}}").unwrap(); + } + }, + _ => {} } printer.path.finish(hash) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index d380cb9a19b78..530221555c52e 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -46,6 +46,13 @@ pub(super) fn mangle<'tcx>( ty::InstanceDef::VTableShim(_) => Some("vtable"), ty::InstanceDef::ReifyShim(_) => Some("reify"), + ty::InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. } + | ty::InstanceDef::CoroutineKindShim { target_kind, .. } => match target_kind { + ty::ClosureKind::Fn => unreachable!(), + ty::ClosureKind::FnMut => Some("fn_mut"), + ty::ClosureKind::FnOnce => Some("fn_once"), + }, + _ => None, }; diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index e023283a70957..7b95b4d03a6f3 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -145,7 +145,7 @@ fn fn_sig_for_fn_abi<'tcx>( ) } ty::Coroutine(did, args) => { - // FIXME(async_closures): This isn't right for `CoroutineByMoveShim`. + // FIXME(async_closures): This isn't right for `CoroutineKindShim`. let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let sig = args.as_coroutine().sig(); diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir new file mode 100644 index 0000000000000..1fae40c5f4004 --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir @@ -0,0 +1,47 @@ +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move + +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug a => (_1.0: i32); + debug b => (_1.1: i32); + let mut _0: (); + let _3: i32; + scope 1 { + debug a => _3; + let _4: &i32; + scope 2 { + debug a => _4; + let _5: &i32; + scope 3 { + debug b => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = (_1.0: i32); + FakeRead(ForLet(None), _3); + StorageLive(_4); + _4 = &_3; + FakeRead(ForLet(None), _4); + StorageLive(_5); + _5 = &(_1.1: i32); + FakeRead(ForLet(None), _5); + _0 = const (); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir new file mode 100644 index 0000000000000..1fae40c5f4004 --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir @@ -0,0 +1,47 @@ +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move + +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug a => (_1.0: i32); + debug b => (_1.1: i32); + let mut _0: (); + let _3: i32; + scope 1 { + debug a => _3; + let _4: &i32; + scope 2 { + debug a => _4; + let _5: &i32; + scope 3 { + debug b => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = (_1.0: i32); + FakeRead(ForLet(None), _3); + StorageLive(_4); + _4 = &_3; + FakeRead(ForLet(None), _4); + StorageLive(_5); + _5 = &(_1.1: i32); + FakeRead(ForLet(None), _5); + _0 = const (); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-abort.mir new file mode 100644 index 0000000000000..9886d6f68a41c --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-abort.mir @@ -0,0 +1,47 @@ +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_mut + +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug a => (_1.0: i32); + debug b => (*(_1.1: &i32)); + let mut _0: (); + let _3: i32; + scope 1 { + debug a => _3; + let _4: &i32; + scope 2 { + debug a => _4; + let _5: &i32; + scope 3 { + debug b => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = (_1.0: i32); + FakeRead(ForLet(None), _3); + StorageLive(_4); + _4 = &_3; + FakeRead(ForLet(None), _4); + StorageLive(_5); + _5 = &(*(_1.1: &i32)); + FakeRead(ForLet(None), _5); + _0 = const (); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-unwind.mir new file mode 100644 index 0000000000000..9886d6f68a41c --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-unwind.mir @@ -0,0 +1,47 @@ +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_mut + +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug a => (_1.0: i32); + debug b => (*(_1.1: &i32)); + let mut _0: (); + let _3: i32; + scope 1 { + debug a => _3; + let _4: &i32; + scope 2 { + debug a => _4; + let _5: &i32; + scope 3 { + debug b => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = (_1.0: i32); + FakeRead(ForLet(None), _3); + StorageLive(_4); + _4 = &_3; + FakeRead(ForLet(None), _4); + StorageLive(_5); + _5 = &(*(_1.1: &i32)); + FakeRead(ForLet(None), _5); + _0 = const (); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir new file mode 100644 index 0000000000000..7df4eb492605b --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir @@ -0,0 +1,10 @@ +// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move + +fn main::{closure#0}::{closure#0}(_1: {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}; + + bb0: { + _0 = {coroutine@$DIR/async_closure_shims.rs:39:53: 42:10 (#0)} { a: move _2, b: move (_1.0: i32) }; + return; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir new file mode 100644 index 0000000000000..7df4eb492605b --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir @@ -0,0 +1,10 @@ +// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move + +fn main::{closure#0}::{closure#0}(_1: {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}; + + bb0: { + _0 = {coroutine@$DIR/async_closure_shims.rs:39:53: 42:10 (#0)} { a: move _2, b: move (_1.0: i32) }; + return; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir new file mode 100644 index 0000000000000..517b8d0dd883b --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir @@ -0,0 +1,16 @@ +// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut + +fn main::{closure#0}::{closure#0}(_1: &mut {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} { + debug a => _2; + debug b => ((*_1).0: i32); + let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}; + let mut _3: &i32; + + bb0: { + StorageLive(_3); + _3 = &((*_1).0: i32); + _0 = {coroutine@$DIR/async_closure_shims.rs:39:53: 42:10 (#0)} { a: _2, b: move _3 }; + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir new file mode 100644 index 0000000000000..517b8d0dd883b --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir @@ -0,0 +1,16 @@ +// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut + +fn main::{closure#0}::{closure#0}(_1: &mut {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} { + debug a => _2; + debug b => ((*_1).0: i32); + let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}; + let mut _3: &i32; + + bb0: { + StorageLive(_3); + _3 = &((*_1).0: i32); + _0 = {coroutine@$DIR/async_closure_shims.rs:39:53: 42:10 (#0)} { a: _2, b: move _3 }; + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs new file mode 100644 index 0000000000000..ef3bdaaa145a3 --- /dev/null +++ b/tests/mir-opt/async_closure_shims.rs @@ -0,0 +1,46 @@ +// edition:2021 +// skip-filecheck +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +#![feature(async_closure, noop_waker, async_fn_traits)] + +use std::future::Future; +use std::ops::{AsyncFnMut, AsyncFnOnce}; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match fut.as_mut().poll(ctx) { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} + +async fn call_mut(f: &mut impl AsyncFnMut(i32)) { + f(0).await; +} + +async fn call_once(f: impl AsyncFnOnce(i32)) { + f(1).await; +} + +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.mir +fn main() { + block_on(async { + let b = 2i32; + let mut async_closure = async move |a: i32| { + let a = &a; + let b = &b; + }; + call_mut(&mut async_closure).await; + call_once(async_closure).await; + }); +} diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs new file mode 100644 index 0000000000000..8d7dc6a276b90 --- /dev/null +++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs @@ -0,0 +1,23 @@ +// aux-build:block-on.rs +// edition:2021 +// run-pass + +// FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. +// ignore-pass (test emits codegen-time warnings) + +#![feature(async_closure, async_fn_traits)] + +extern crate block_on; + +use std::ops::AsyncFnMut; + +fn main() { + block_on::block_on(async { + let x = async || {}; + + async fn needs_async_fn_mut(mut x: impl AsyncFnMut()) { + x().await; + } + needs_async_fn_mut(x).await; + }); +} diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr new file mode 100644 index 0000000000000..48917e8b23fde --- /dev/null +++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr @@ -0,0 +1 @@ +WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), [i16, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>.See . diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr index 9ae4692f003ef..978a5a653f97d 100644 --- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr +++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr @@ -1,2 +1 @@ -WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()])>.See . -WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected *mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()]), found *mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#1}), []), ()]).See . +WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>.See . diff --git a/tests/ui/async-await/async-closures/def-path.rs b/tests/ui/async-await/async-closures/def-path.rs index 2883a1715b0ac..87e99ddda64b3 100644 --- a/tests/ui/async-await/async-closures/def-path.rs +++ b/tests/ui/async-await/async-closures/def-path.rs @@ -8,7 +8,7 @@ fn main() { //~^ NOTE the expected `async` closure body let () = x(); //~^ ERROR mismatched types - //~| NOTE this expression has type `{static main::{closure#0}::{closure#0} upvar_tys= + //~| NOTE this expression has type `{static main::{closure#0}::{closure#0}< //~| NOTE expected `async` closure body, found `()` - //~| NOTE expected `async` closure body `{static main::{closure#0}::{closure#0} + //~| NOTE expected `async` closure body `{static main::{closure#0}::{closure#0}< } diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr index 4b37e50aac459..dae45825f370d 100644 --- a/tests/ui/async-await/async-closures/def-path.stderr +++ b/tests/ui/async-await/async-closures/def-path.stderr @@ -5,11 +5,11 @@ LL | let x = async || {}; | -- the expected `async` closure body LL | LL | let () = x(); - | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?7t witness=?8t}` + | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?15t witness=?6t}` | | | expected `async` closure body, found `()` | - = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?7t witness=?8t}` + = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?15t witness=?6t}` found unit type `()` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/async-closures/drop.rs b/tests/ui/async-await/async-closures/drop.rs new file mode 100644 index 0000000000000..1b7f2f8a600d0 --- /dev/null +++ b/tests/ui/async-await/async-closures/drop.rs @@ -0,0 +1,40 @@ +// aux-build:block-on.rs +// edition:2018 +// run-pass +// check-run-results + +#![feature(async_closure, async_fn_traits)] +#![allow(unused)] + +extern crate block_on; + +use std::ops::AsyncFnOnce; + +struct DropMe(i32); + +impl Drop for DropMe { + fn drop(&mut self) { + println!("{} was dropped", self.0); + } +} + +async fn call_once(f: impl AsyncFnOnce()) { + println!("before call"); + let fut = Box::pin(f()); + println!("after call"); + drop(fut); + println!("future dropped"); +} + +fn main() { + block_on::block_on(async { + let d = DropMe(42); + let async_closure = async move || { + let d = &d; + println!("called"); + }; + + call_once(async_closure).await; + println!("after"); + }); +} diff --git a/tests/ui/async-await/async-closures/drop.run.stdout b/tests/ui/async-await/async-closures/drop.run.stdout new file mode 100644 index 0000000000000..ab233f491ba65 --- /dev/null +++ b/tests/ui/async-await/async-closures/drop.run.stdout @@ -0,0 +1,5 @@ +before call +after call +42 was dropped +future dropped +after diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs new file mode 100644 index 0000000000000..98065c3c71109 --- /dev/null +++ b/tests/ui/async-await/async-closures/mangle.rs @@ -0,0 +1,36 @@ +// aux-build:block-on.rs +// edition:2021 +// build-pass +// revisions: v0 legacy +//[v0] compile-flags: -Csymbol-mangling-version=v0 +//[legacy] compile-flags: -Csymbol-mangling-version=legacy -Zunstable-options + +// FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. +// ignore-pass (test emits codegen-time warnings) + +#![feature(async_closure, noop_waker, async_fn_traits)] + +extern crate block_on; + +use std::future::Future; +use std::ops::{AsyncFnMut, AsyncFnOnce}; +use std::pin::pin; +use std::task::*; + +async fn call_mut(f: &mut impl AsyncFnMut()) { + f().await; +} + +async fn call_once(f: impl AsyncFnOnce()) { + f().await; +} + +fn main() { + block_on::block_on(async { + let mut async_closure = async move || { + println!("called"); + }; + call_mut(&mut async_closure).await; + call_once(async_closure).await; + }); +} From 827bfe4154a9679a173755bb2098b863ef890f70 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 2 Feb 2024 09:25:16 +0000 Subject: [PATCH 593/676] Document `async_fn_traits` --- .../src/library-features/async-fn-traits.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/async-fn-traits.md diff --git a/src/doc/unstable-book/src/library-features/async-fn-traits.md b/src/doc/unstable-book/src/library-features/async-fn-traits.md new file mode 100644 index 0000000000000..e1c3f067e5b2b --- /dev/null +++ b/src/doc/unstable-book/src/library-features/async-fn-traits.md @@ -0,0 +1,13 @@ +# `async_fn_traits` + +See Also: [`fn_traits`](../library-features/fn-traits.md) + +---- + +The `async_fn_traits` feature allows for implementation of the [`AsyncFn*`] traits +for creating custom closure-like types that return futures. + +[`AsyncFn*`]: ../../std/ops/trait.AsyncFn.html + +The main difference to the `Fn*` family of traits is that `AsyncFn` can return a future +that borrows from itself (`FnOnce::Output` has no lifetime parameters, while `AsyncFn::CallFuture` does). From ed7fca1f8805b4348b801f23f444e0dda42f7aed Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Feb 2024 02:53:06 +0000 Subject: [PATCH 594/676] Fudge coroutine argument for CoroutineKindShim in fn_sig_for_fn_abi --- compiler/rustc_ty_utils/src/abi.rs | 36 +++++++++++++++++-- .../async-fn-mut-for-async-fn.stderr | 1 - .../async-fn-once-for-async-fn.stderr | 1 - 3 files changed, 34 insertions(+), 4 deletions(-) delete mode 100644 tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr delete mode 100644 tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 7b95b4d03a6f3..0542ef4ecf902 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -145,8 +145,6 @@ fn fn_sig_for_fn_abi<'tcx>( ) } ty::Coroutine(did, args) => { - // FIXME(async_closures): This isn't right for `CoroutineKindShim`. - let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let sig = args.as_coroutine().sig(); @@ -157,6 +155,40 @@ fn fn_sig_for_fn_abi<'tcx>( var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; + + let mut ty = ty; + // When this `Closure` comes from a `CoroutineKindShim`, + // make sure we respect the `target_kind` in that shim. + // FIXME(async_closures): This shouldn't be needed, and we should be populating + // a separate def-id for these bodies. + if let InstanceDef::CoroutineKindShim { target_kind, .. } = instance.def { + // Grab the parent coroutine-closure. It has the same args for the purposes + // of substitution, so this will be okay to do. + let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx + .instantiate_and_normalize_erasing_regions( + args, + param_env, + tcx.type_of(tcx.parent(did)), + ) + .kind() + else { + bug!("CoroutineKindShim comes from calling a coroutine-closure"); + }; + let coroutine_closure_args = coroutine_closure_args.as_coroutine_closure(); + ty = tcx.instantiate_bound_regions_with_erased( + coroutine_closure_args.coroutine_closure_sig().map_bound(|sig| { + sig.to_coroutine_given_kind_and_upvars( + tcx, + coroutine_closure_args.parent_args(), + did, + target_kind, + tcx.lifetimes.re_erased, + coroutine_closure_args.tupled_upvars_ty(), + coroutine_closure_args.coroutine_captures_by_ref_ty(), + ) + }), + ); + } let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr deleted file mode 100644 index 48917e8b23fde..0000000000000 --- a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr +++ /dev/null @@ -1 +0,0 @@ -WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), [i16, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>.See . diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr deleted file mode 100644 index 978a5a653f97d..0000000000000 --- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr +++ /dev/null @@ -1 +0,0 @@ -WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>.See . From 0b6af718d85a2639854ad09730f5f39aa5f70f9a Mon Sep 17 00:00:00 2001 From: trevyn <230691+trevyn@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:53:28 -0800 Subject: [PATCH 595/676] Create helper `maybe_report_similar_assoc_fn` --- .../rustc_hir_analysis/src/astconv/errors.rs | 51 ++++++++++++++++++ .../rustc_hir_analysis/src/astconv/mod.rs | 52 +------------------ tests/ui/suggestions/issue-109195.rs | 10 ++-- tests/ui/suggestions/issue-109195.stderr | 18 +++---- 4 files changed, 66 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 407517b15ef5e..869e218400639 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -14,6 +14,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::FulfillmentError; +use rustc_middle::query::Key; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; @@ -859,6 +860,56 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.set_tainted_by_errors(err.emit()); } + + /// On ambiguous associated type, look for an associated function whose name matches the + /// extended path and, if found, emit an E0223 error with a structured suggestion. + /// e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195) + pub(crate) fn maybe_report_similar_assoc_fn( + &self, + span: Span, + qself_ty: Ty<'tcx>, + qself: &hir::Ty<'_>, + ) -> Result<(), ErrorGuaranteed> { + let tcx = self.tcx(); + if let Some((_, node)) = tcx.hir().parent_iter(qself.hir_id).skip(1).next() + && let hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::Path(hir::QPath::TypeRelative( + hir::Ty { + kind: + hir::TyKind::Path(hir::QPath::TypeRelative( + _, + hir::PathSegment { ident: ident2, .. }, + )), + .. + }, + hir::PathSegment { ident: ident3, .. }, + )), + .. + }) = node + && let Some(ty_def_id) = qself_ty.ty_def_id() + && let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id) + && let name = format!("{ident2}_{ident3}") + && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx + .associated_items(inherent_impl) + .filter_by_name_unhygienic(Symbol::intern(&name)) + .next() + { + let reported = + struct_span_code_err!(tcx.dcx(), span, E0223, "ambiguous associated type") + .with_span_suggestion_verbose( + ident2.span.to(ident3.span), + format!("there is an associated function with a similar name: `{name}`"), + name, + Applicability::MaybeIncorrect, + ) + .emit(); + self.set_tainted_by_errors(reported); + Err(reported) + } else { + Ok(()) + } + } } /// Emits an error regarding forbidden type binding associations diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index d69f366a66c95..cfd38fb48f472 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -29,7 +29,6 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; -use rustc_middle::query::Key; use rustc_middle::ty::{ self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty, TyCtxt, TypeVisitableExt, @@ -1374,56 +1373,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) .emit() // Already reported in an earlier stage. } else { - // suggest methods that look similar to the path - // e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195) - for (_, node) in tcx.hir().parent_iter(qself.hir_id) { - if let hir::Node::Expr(hir::Expr { - kind: - hir::ExprKind::Path(hir::QPath::TypeRelative( - hir::Ty { - kind: - hir::TyKind::Path(hir::QPath::TypeRelative( - _, - hir::PathSegment { ident: ident2, .. }, - )), - .. - }, - hir::PathSegment { ident: ident3, .. }, - )), - .. - }) = node - { - let name = format!("{ident2}_{ident3}"); - if if let Some(ty_def_id) = qself_ty.ty_def_id() - && let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id) - && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx - .associated_items(inherent_impl) - .filter_by_name_unhygienic(Symbol::intern(&name)) - .next() - { - true - } else { - qself_ty.is_str() - && ["from_utf8", "from_utf8_mut"].contains(&name.as_str()) - } { - let reported = struct_span_code_err!( - tcx.dcx(), - span, - E0223, - "ambiguous associated type" - ) - .with_span_suggestion_verbose( - ident2.span.to(ident3.span), - format!("you might have meant to use `{name}`"), - name, - Applicability::MaybeIncorrect, - ) - .emit(); - self.set_tainted_by_errors(reported); - return Err(reported); - } - } - } + self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?; let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident); diff --git a/tests/ui/suggestions/issue-109195.rs b/tests/ui/suggestions/issue-109195.rs index badb859dbb701..cc499b0d77618 100644 --- a/tests/ui/suggestions/issue-109195.rs +++ b/tests/ui/suggestions/issue-109195.rs @@ -1,20 +1,20 @@ fn main() { String::from::utf8; //~^ ERROR ambiguous associated type [E0223] - //~| HELP you might have meant to use `from_utf8` + //~| HELP there is an associated function with a similar name: `from_utf8` String::from::utf8(); //~^ ERROR ambiguous associated type [E0223] - //~| HELP you might have meant to use `from_utf8` + //~| HELP there is an associated function with a similar name: `from_utf8` String::from::utf16(); //~^ ERROR ambiguous associated type [E0223] - //~| HELP you might have meant to use `from_utf16` + //~| HELP there is an associated function with a similar name: `from_utf16` String::from::method_that_doesnt_exist(); //~^ ERROR ambiguous associated type [E0223] //~| HELP if there were a trait named `Example` with associated type `from` str::from::utf8(); //~^ ERROR ambiguous associated type [E0223] - //~| HELP you might have meant to use `from_utf8` + //~| HELP if there were a trait named `Example` with associated type `from` str::from::utf8_mut(); //~^ ERROR ambiguous associated type [E0223] - //~| HELP you might have meant to use `from_utf8_mut` + //~| HELP if there were a trait named `Example` with associated type `from` } diff --git a/tests/ui/suggestions/issue-109195.stderr b/tests/ui/suggestions/issue-109195.stderr index 5c9ef9f98f513..10cf9cfd28ca7 100644 --- a/tests/ui/suggestions/issue-109195.stderr +++ b/tests/ui/suggestions/issue-109195.stderr @@ -4,7 +4,7 @@ error[E0223]: ambiguous associated type LL | String::from::utf8; | ^^^^^^^^^^^^ | -help: you might have meant to use `from_utf8` +help: there is an associated function with a similar name: `from_utf8` | LL | String::from_utf8; | ~~~~~~~~~ @@ -15,7 +15,7 @@ error[E0223]: ambiguous associated type LL | String::from::utf8(); | ^^^^^^^^^^^^ | -help: you might have meant to use `from_utf8` +help: there is an associated function with a similar name: `from_utf8` | LL | String::from_utf8(); | ~~~~~~~~~ @@ -26,7 +26,7 @@ error[E0223]: ambiguous associated type LL | String::from::utf16(); | ^^^^^^^^^^^^ | -help: you might have meant to use `from_utf16` +help: there is an associated function with a similar name: `from_utf16` | LL | String::from_utf16(); | ~~~~~~~~~~ @@ -48,10 +48,10 @@ error[E0223]: ambiguous associated type LL | str::from::utf8(); | ^^^^^^^^^ | -help: you might have meant to use `from_utf8` +help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path | -LL | str::from_utf8(); - | ~~~~~~~~~ +LL | ::from::utf8(); + | ~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/issue-109195.rs:17:5 @@ -59,10 +59,10 @@ error[E0223]: ambiguous associated type LL | str::from::utf8_mut(); | ^^^^^^^^^ | -help: you might have meant to use `from_utf8_mut` +help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path | -LL | str::from_utf8_mut(); - | ~~~~~~~~~~~~~ +LL | ::from::utf8_mut(); + | ~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 6 previous errors From a939bad513e6201d7be76c13080fc0cc901bd658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Jan 2024 20:34:29 +0000 Subject: [PATCH 596/676] Suggest turnging `if let` into irrefutable `let` if appropriate When encountering an `if let` tail expression without an `else` arm for an enum with a single variant, suggest writing an irrefutable `let` binding instead. ``` error[E0317]: `if` may be missing an `else` clause --> $DIR/irrefutable-if-let-without-else.rs:8:5 | LL | fn foo(x: Enum) -> i32 { | --- expected `i32` because of this return type LL | / if let Enum::Variant(value) = x { LL | | value LL | | } | |_____^ expected `i32`, found `()` | = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type help: consider using an irrefutable `let` binding instead | LL ~ let Enum::Variant(value) = x; LL ~ value | ``` Fix #61788. --- compiler/rustc_hir_typeck/src/_match.rs | 116 +++++++++++++++--- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../irrefutable-if-let-without-else.fixed | 25 ++++ .../irrefutable-if-let-without-else.rs | 28 +++++ .../irrefutable-if-let-without-else.stderr | 61 +++++++++ 5 files changed, 214 insertions(+), 18 deletions(-) create mode 100644 tests/ui/binding/irrefutable-if-let-without-else.fixed create mode 100644 tests/ui/binding/irrefutable-if-let-without-else.rs create mode 100644 tests/ui/binding/irrefutable-if-let-without-else.stderr diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index cf1f232229d51..7ea0469deddee 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -1,7 +1,11 @@ use crate::coercion::{AsCoercionSite, CoerceMany}; use crate::{Diverges, Expectation, FnCtxt, Needs}; -use rustc_errors::Diagnostic; -use rustc_hir::{self as hir, ExprKind}; +use rustc_errors::{Applicability, Diagnostic}; +use rustc_hir::{ + self as hir, + def::{CtorOf, DefKind, Res}, + ExprKind, PatKind, +}; use rustc_hir_pretty::ty_to_string; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; @@ -273,7 +277,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns `true` if there was an error forcing the coercion to the `()` type. pub(super) fn if_fallback_coercion( &self, - span: Span, + if_span: Span, + cond_expr: &'tcx hir::Expr<'tcx>, then_expr: &'tcx hir::Expr<'tcx>, coercion: &mut CoerceMany<'tcx, '_, T>, ) -> bool @@ -283,29 +288,106 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If this `if` expr is the parent's function return expr, // the cause of the type coercion is the return type, point at it. (#25228) let hir_id = self.tcx.hir().parent_id(self.tcx.hir().parent_id(then_expr.hir_id)); - let ret_reason = self.maybe_get_coercion_reason(hir_id, span); - let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse); + let ret_reason = self.maybe_get_coercion_reason(hir_id, if_span); + let cause = self.cause(if_span, ObligationCauseCode::IfExpressionWithNoElse); let mut error = false; coercion.coerce_forced_unit( self, &cause, - |err| { - if let Some((span, msg)) = &ret_reason { - err.span_label(*span, msg.clone()); - } else if let ExprKind::Block(block, _) = &then_expr.kind - && let Some(expr) = &block.expr - { - err.span_label(expr.span, "found here"); - } - err.note("`if` expressions without `else` evaluate to `()`"); - err.help("consider adding an `else` block that evaluates to the expected type"); - error = true; - }, + |err| self.explain_if_expr(err, ret_reason, if_span, cond_expr, then_expr, &mut error), false, ); error } + /// Explain why `if` expressions without `else` evaluate to `()` and detect likely irrefutable + /// `if let PAT = EXPR {}` expressions that could be turned into `let PAT = EXPR;`. + fn explain_if_expr( + &self, + err: &mut Diagnostic, + ret_reason: Option<(Span, String)>, + if_span: Span, + cond_expr: &'tcx hir::Expr<'tcx>, + then_expr: &'tcx hir::Expr<'tcx>, + error: &mut bool, + ) { + if let Some((if_span, msg)) = ret_reason { + err.span_label(if_span, msg.clone()); + } else if let ExprKind::Block(block, _) = then_expr.kind + && let Some(expr) = block.expr + { + err.span_label(expr.span, "found here"); + } + err.note("`if` expressions without `else` evaluate to `()`"); + err.help("consider adding an `else` block that evaluates to the expected type"); + *error = true; + if let ExprKind::Let(hir::Let { span, pat, init, .. }) = cond_expr.kind + && let ExprKind::Block(block, _) = then_expr.kind + // Refutability checks occur on the MIR, so we approximate it here by checking + // if we have an enum with a single variant or a struct in the pattern. + && let PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..) = pat.kind + && let hir::QPath::Resolved(_, path) = qpath + { + match path.res { + Res::Def(DefKind::Ctor(CtorOf::Struct, _), _) => { + // Structs are always irrefutable. Their fields might not be, but we + // don't check for that here, it's only an approximation. + } + Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) + if self + .tcx + .adt_def(self.tcx.parent(self.tcx.parent(def_id))) + .variants() + .len() + == 1 => + { + // There's only a single variant in the `enum`, so we can suggest the + // irrefutable `let` instead of `if let`. + } + _ => return, + } + + let mut sugg = vec![ + // Remove the `if` + (if_span.until(*span), String::new()), + ]; + match (block.stmts, block.expr) { + ([first, ..], Some(expr)) => { + let padding = self + .tcx + .sess + .source_map() + .indentation_before(first.span) + .unwrap_or_else(|| String::new()); + sugg.extend([ + (init.span.between(first.span), format!(";\n{padding}")), + (expr.span.shrink_to_hi().with_hi(block.span.hi()), String::new()), + ]); + } + ([], Some(expr)) => { + let padding = self + .tcx + .sess + .source_map() + .indentation_before(expr.span) + .unwrap_or_else(|| String::new()); + sugg.extend([ + (init.span.between(expr.span), format!(";\n{padding}")), + (expr.span.shrink_to_hi().with_hi(block.span.hi()), String::new()), + ]); + } + // If there's no value in the body, then the `if` expression would already + // be of type `()`, so checking for those cases is unnecessary. + (_, None) => return, + } + err.multipart_suggestion( + "consider using an irrefutable `let` binding instead", + sugg, + Applicability::MaybeIncorrect, + ); + } + } + pub fn maybe_get_coercion_reason( &self, hir_id: hir::HirId, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2bbef11fa2450..4f96b1fde1a6d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1118,7 +1118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We won't diverge unless both branches do (or the condition does). self.diverges.set(cond_diverges | then_diverges & else_diverges); } else { - self.if_fallback_coercion(sp, then_expr, &mut coerce); + self.if_fallback_coercion(sp, cond_expr, then_expr, &mut coerce); // If the condition is false we can't diverge. self.diverges.set(cond_diverges); diff --git a/tests/ui/binding/irrefutable-if-let-without-else.fixed b/tests/ui/binding/irrefutable-if-let-without-else.fixed new file mode 100644 index 0000000000000..3d7f4695ca864 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.fixed @@ -0,0 +1,25 @@ +// run-rustfix +enum Enum { + Variant(i32), +} +struct Struct(i32); + +fn foo(x: Enum) -> i32 { + let Enum::Variant(value) = x; + value +} +fn bar(x: Enum) -> i32 { + let Enum::Variant(value) = x; + let x = value + 1; + x +} +fn baz(x: Struct) -> i32 { + let Struct(value) = x; + let x = value + 1; + x +} +fn main() { + let _ = foo(Enum::Variant(42)); + let _ = bar(Enum::Variant(42)); + let _ = baz(Struct(42)); +} diff --git a/tests/ui/binding/irrefutable-if-let-without-else.rs b/tests/ui/binding/irrefutable-if-let-without-else.rs new file mode 100644 index 0000000000000..5aaf4ace3f821 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.rs @@ -0,0 +1,28 @@ +// run-rustfix +enum Enum { + Variant(i32), +} +struct Struct(i32); + +fn foo(x: Enum) -> i32 { + if let Enum::Variant(value) = x { //~ ERROR `if` may be missing an `else` clause + value + } +} +fn bar(x: Enum) -> i32 { + if let Enum::Variant(value) = x { //~ ERROR `if` may be missing an `else` clause + let x = value + 1; + x + } +} +fn baz(x: Struct) -> i32 { + if let Struct(value) = x { //~ ERROR `if` may be missing an `else` clause + let x = value + 1; + x + } +} +fn main() { + let _ = foo(Enum::Variant(42)); + let _ = bar(Enum::Variant(42)); + let _ = baz(Struct(42)); +} diff --git a/tests/ui/binding/irrefutable-if-let-without-else.stderr b/tests/ui/binding/irrefutable-if-let-without-else.stderr new file mode 100644 index 0000000000000..e234cfdd945f3 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.stderr @@ -0,0 +1,61 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:8:5 + | +LL | fn foo(x: Enum) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Enum::Variant(value) = x { +LL | | value +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Enum::Variant(value) = x; +LL ~ value + | + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:13:5 + | +LL | fn bar(x: Enum) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Enum::Variant(value) = x { +LL | | let x = value + 1; +LL | | x +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Enum::Variant(value) = x; +LL ~ let x = value + 1; +LL ~ x + | + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:19:5 + | +LL | fn baz(x: Struct) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Struct(value) = x { +LL | | let x = value + 1; +LL | | x +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Struct(value) = x; +LL ~ let x = value + 1; +LL ~ x + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0317`. From 25635b9a96ebbbd87bbbfb1d7c31004651179f2a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Feb 2024 21:48:58 +0100 Subject: [PATCH 597/676] miri: fix ICE with symbolic alignment check on extern static --- .../src/interpret/validity.rs | 5 +-- src/tools/miri/src/borrow_tracker/mod.rs | 2 +- src/tools/miri/src/machine.rs | 34 +++++++++++-------- src/tools/miri/src/provenance_gc.rs | 1 + src/tools/miri/src/shims/foreign_items.rs | 12 +++---- ...88-ice-symbolic-alignment-extern-static.rs | 12 +++++++ ...ce-symbolic-alignment-extern-static.stderr | 14 ++++++++ .../miri/tests/pass/align_offset_symbolic.rs | 23 ++++++++++++- 8 files changed, 76 insertions(+), 27 deletions(-) create mode 100644 src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.rs create mode 100644 src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index b5cd32595201f..4dbea54e22470 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -992,10 +992,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Complain about any other kind of error -- those are bad because we'd like to // report them in a way that shows *where* in the value the issue lies. Err(err) => { - bug!( - "Unexpected Undefined Behavior error during validation: {}", - self.format_error(err) - ); + bug!("Unexpected error during validation: {}", self.format_error(err)); } } } diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 74ff6ed4e0abe..46f96a715f1c6 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -383,7 +383,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // will never cause UB on the pointer itself. let (_, _, kind) = this.get_alloc_info(*alloc_id); if matches!(kind, AllocKind::LiveData) { - let alloc_extra = this.get_alloc_extra(*alloc_id).unwrap(); + let alloc_extra = this.get_alloc_extra(*alloc_id)?; // can still fail for `extern static` let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap(); alloc_borrow_tracker.release_protector(&this.machine, borrow_tracker, *tag)?; } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 946887637fff8..40d041c8fdb16 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -2,7 +2,7 @@ //! `Machine` trait. use std::borrow::Cow; -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fmt; use std::path::Path; @@ -336,20 +336,11 @@ pub struct AllocExtra<'tcx> { /// if this allocation is leakable. The backtrace is not /// pruned yet; that should be done before printing it. pub backtrace: Option>>, - /// An offset inside this allocation that was deemed aligned even for symbolic alignment checks. - /// Invariant: the promised alignment will never be less than the native alignment of this allocation. - pub symbolic_alignment: Cell>, } impl VisitProvenance for AllocExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let AllocExtra { - borrow_tracker, - data_race, - weak_memory, - backtrace: _, - symbolic_alignment: _, - } = self; + let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _ } = self; borrow_tracker.visit_provenance(visit); data_race.visit_provenance(visit); @@ -572,6 +563,14 @@ pub struct MiriMachine<'mir, 'tcx> { /// that is fixed per stack frame; this lets us have sometimes different results for the /// same const while ensuring consistent results within a single call. const_cache: RefCell, usize), OpTy<'tcx, Provenance>>>, + + /// For each allocation, an offset inside that allocation that was deemed aligned even for + /// symbolic alignment checks. This cannot be stored in `AllocExtra` since it needs to be + /// tracked for vtables and function allocations as well as regular allocations. + /// + /// Invariant: the promised alignment will never be less than the native alignment of the + /// allocation. + pub(crate) symbolic_alignment: RefCell>, } impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { @@ -698,6 +697,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { collect_leak_backtraces: config.collect_leak_backtraces, allocation_spans: RefCell::new(FxHashMap::default()), const_cache: RefCell::new(FxHashMap::default()), + symbolic_alignment: RefCell::new(FxHashMap::default()), } } @@ -810,6 +810,7 @@ impl VisitProvenance for MiriMachine<'_, '_> { collect_leak_backtraces: _, allocation_spans: _, const_cache: _, + symbolic_alignment: _, } = self; threads.visit_provenance(visit); @@ -893,9 +894,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { return None; } // Let's see which alignment we have been promised for this allocation. - let alloc_info = ecx.get_alloc_extra(alloc_id).unwrap(); // cannot fail since the allocation is live - let (promised_offset, promised_align) = - alloc_info.symbolic_alignment.get().unwrap_or((Size::ZERO, alloc_align)); + let (promised_offset, promised_align) = ecx + .machine + .symbolic_alignment + .borrow() + .get(&alloc_id) + .copied() + .unwrap_or((Size::ZERO, alloc_align)); if promised_align < align { // Definitely not enough. Some(Misalignment { has: promised_align, required: align }) @@ -1132,7 +1137,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { data_race: race_alloc, weak_memory: buffer_alloc, backtrace, - symbolic_alignment: Cell::new(None), }, |ptr| ecx.global_base_pointer(ptr), )?; diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs index ab178f82d9fde..347951ce37270 100644 --- a/src/tools/miri/src/provenance_gc.rs +++ b/src/tools/miri/src/provenance_gc.rs @@ -196,6 +196,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let allocs = LiveAllocs { ecx: this, collected: allocs }; this.machine.allocation_spans.borrow_mut().retain(|id, _| allocs.is_live(*id)); + this.machine.symbolic_alignment.borrow_mut().retain(|id, _| allocs.is_live(*id)); this.machine.intptrcast.borrow_mut().remove_unreachable_allocs(&allocs); if let Some(borrow_tracker) = &this.machine.borrow_tracker { borrow_tracker.borrow_mut().remove_unreachable_allocs(&allocs); diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index a002f2aad057c..25654248db41a 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -585,17 +585,17 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr) { let (_size, alloc_align, _kind) = this.get_alloc_info(alloc_id); - // Not `get_alloc_extra_mut`, need to handle read-only allocations! - let alloc_extra = this.get_alloc_extra(alloc_id)?; // If the newly promised alignment is bigger than the native alignment of this // allocation, and bigger than the previously promised alignment, then set it. if align > alloc_align - && !alloc_extra + && !this + .machine .symbolic_alignment - .get() - .is_some_and(|(_, old_align)| align <= old_align) + .get_mut() + .get(&alloc_id) + .is_some_and(|&(_, old_align)| align <= old_align) { - alloc_extra.symbolic_alignment.set(Some((offset, align))); + this.machine.symbolic_alignment.get_mut().insert(alloc_id, (offset, align)); } } } diff --git a/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.rs b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.rs new file mode 100644 index 0000000000000..446040749822e --- /dev/null +++ b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.rs @@ -0,0 +1,12 @@ +//@compile-flags: -Zmiri-symbolic-alignment-check + +extern "C" { + static _dispatch_queue_attr_concurrent: [u8; 0]; +} + +static DISPATCH_QUEUE_CONCURRENT: &'static [u8; 0] = + unsafe { &_dispatch_queue_attr_concurrent }; + +fn main() { + let _val = *DISPATCH_QUEUE_CONCURRENT; //~ERROR: is not supported +} diff --git a/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr new file mode 100644 index 0000000000000..a4249d2e8816d --- /dev/null +++ b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr @@ -0,0 +1,14 @@ +error: unsupported operation: `extern` static `_dispatch_queue_attr_concurrent` from crate `issue_miri_3288_ice_symbolic_alignment_extern_static` is not supported by Miri + --> $DIR/issue-miri-3288-ice-symbolic-alignment-extern-static.rs:LL:CC + | +LL | let _val = *DISPATCH_QUEUE_CONCURRENT; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `extern` static `_dispatch_queue_attr_concurrent` from crate `issue_miri_3288_ice_symbolic_alignment_extern_static` is not supported by Miri + | + = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support + = note: BACKTRACE: + = note: inside `main` at $DIR/issue-miri-3288-ice-symbolic-alignment-extern-static.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/align_offset_symbolic.rs b/src/tools/miri/tests/pass/align_offset_symbolic.rs index 4df364bac7ad9..e96f11b1efa72 100644 --- a/src/tools/miri/tests/pass/align_offset_symbolic.rs +++ b/src/tools/miri/tests/pass/align_offset_symbolic.rs @@ -1,6 +1,8 @@ //@compile-flags: -Zmiri-symbolic-alignment-check #![feature(strict_provenance)] +use std::mem; + fn test_align_to() { const N: usize = 4; let d = Box::new([0u32; N]); @@ -68,7 +70,7 @@ fn test_u64_array() { #[repr(align(8))] struct AlignToU64(T); - const BYTE_LEN: usize = std::mem::size_of::<[u64; 4]>(); + const BYTE_LEN: usize = mem::size_of::<[u64; 4]>(); type Data = AlignToU64<[u8; BYTE_LEN]>; fn example(data: &Data) { @@ -101,10 +103,29 @@ fn huge_align() { let _ = std::ptr::invalid::(SIZE).align_offset(SIZE); } +// This shows that we cannot store the promised alignment info in `AllocExtra`, +// since vtables do not have an `AllocExtra`. +fn vtable() { + #[cfg(target_pointer_width = "64")] + type TWOPTR = u128; + #[cfg(target_pointer_width = "32")] + type TWOPTR = u64; + + let ptr: &dyn Send = &0; + let parts: (*const (), *const u8) = unsafe { mem::transmute(ptr) }; + let vtable = parts.1 ; + let offset = vtable.align_offset(mem::align_of::()); + let _vtable_aligned = vtable.wrapping_add(offset) as *const [TWOPTR; 0]; + // FIXME: we can't actually do the access since vtable pointers act like zero-sized allocations. + // Enable the next line once https://github.com/rust-lang/rust/issues/117945 is implemented. + //let _place = unsafe { &*vtable_aligned }; +} + fn main() { test_align_to(); test_from_utf8(); test_u64_array(); test_cstr(); huge_align(); + vtable(); } From 2a06b69ba2600dbcd599641923fdc23b66344f9c Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 26 Jan 2024 11:36:56 +0300 Subject: [PATCH 598/676] llvm-wrapper: remove llvm 12 hack effectively reverts https://github.com/rust-lang/rust/commit/9a8acea78355b604dbeb29bc38bd4dbf7bfce95f --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 6114f7c867807..ed7aa437ddd2e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -945,12 +945,7 @@ LLVMRustOptimize( break; case LLVMRustOptStage::PreLinkThinLTO: MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel); - // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback - // passes may still run afterwards. This means we need to run the buffer passes again. - // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks - // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks. - if (OptimizerLastEPCallbacks.empty()) - NeedThinLTOBufferPasses = false; + NeedThinLTOBufferPasses = false; for (const auto &C : OptimizerLastEPCallbacks) C(MPM, OptLevel); break; From ca35cfb6defe6bdec8ab0419aa682db780142fb7 Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 6 Feb 2024 12:44:40 +0300 Subject: [PATCH 599/676] review --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index ed7aa437ddd2e..3b6bf03686b0d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -934,10 +934,8 @@ LLVMRustOptimize( } else { for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); - if (OptStage != LLVMRustOptStage::PreLinkThinLTO) { - for (const auto &C : OptimizerLastEPCallbacks) - PB.registerOptimizerLastEPCallback(C); - } + for (const auto &C : OptimizerLastEPCallbacks) + PB.registerOptimizerLastEPCallback(C); switch (OptStage) { case LLVMRustOptStage::PreLinkNoLTO: @@ -946,8 +944,6 @@ LLVMRustOptimize( case LLVMRustOptStage::PreLinkThinLTO: MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel); NeedThinLTOBufferPasses = false; - for (const auto &C : OptimizerLastEPCallbacks) - C(MPM, OptLevel); break; case LLVMRustOptStage::PreLinkFatLTO: MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel); From ad3d04c55ec4cbd924b3f7e3a890483b6eb1604d Mon Sep 17 00:00:00 2001 From: Amanda Stjerna Date: Tue, 6 Feb 2024 13:07:51 +0100 Subject: [PATCH 600/676] A drive-by rewrite of give_region_a_name() This rewrite makes the cache-updating nature of the function slightly clearer, using the Entry API into the hash table for region names to capture the update-insert nature of the method. May be marginally more efficient since it only runtime-borrows the map once, but in this context the performance impact is almost certainly completely negligible. --- .../src/diagnostics/region_name.rs | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 15e1066e983a9..c9de36e9064e2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -1,6 +1,7 @@ use std::fmt::{self, Display}; use std::iter; +use rustc_data_structures::fx::IndexEntry; use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -247,25 +248,28 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { assert!(self.regioncx.universal_regions().is_universal_region(fr)); - if let Some(value) = self.region_names.try_borrow_mut().unwrap().get(&fr) { - return Some(value.clone()); - } + match self.region_names.borrow_mut().entry(fr) { + IndexEntry::Occupied(precomputed_name) => Some(precomputed_name.get().clone()), + IndexEntry::Vacant(slot) => { + let new_name = self + .give_name_from_error_region(fr) + .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)) + .or_else(|| { + self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr) + }); + + if let Some(new_name) = &new_name { + slot.insert(new_name.clone()); + } + debug!("give_region_a_name: gave name {:?}", new_name); - let value = self - .give_name_from_error_region(fr) - .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr)); - - if let Some(value) = &value { - self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone()); + new_name + } } - - debug!("give_region_a_name: gave name {:?}", value); - value } /// Checks for the case where `fr` maps to something that the From a2ab48c21b41bd3c842928d84c881b8b780648e4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 4 Jan 2024 16:57:24 +0300 Subject: [PATCH 601/676] resolve: Unload speculatively resolved crates before freezing cstore --- compiler/rustc_metadata/src/creader.rs | 15 ++++++++++++- compiler/rustc_metadata/src/rmeta/decoder.rs | 7 +++++++ .../src/rmeta/decoder/cstore_impl.rs | 15 ++++++++++++- compiler/rustc_resolve/src/late.rs | 21 ++++++++++++------- compiler/rustc_resolve/src/lib.rs | 1 + tests/ui/extern-flag/empty-extern-arg.stderr | 9 ++------ 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index bb02a8a1e4743..c18f0e7b7b938 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -534,7 +534,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { ) -> Option { self.used_extern_options.insert(name); match self.maybe_resolve_crate(name, dep_kind, None) { - Ok(cnum) => Some(cnum), + Ok(cnum) => { + self.cstore.set_used_recursively(cnum); + Some(cnum) + } Err(err) => { let missing_core = self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); @@ -1067,6 +1070,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok() } + + pub fn unload_unused_crates(&mut self) { + for opt_cdata in &mut self.cstore.metas { + if let Some(cdata) = opt_cdata + && !cdata.used() + { + *opt_cdata = None; + } + } + } } fn global_allocator_spans(krate: &ast::Crate) -> Vec { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 20e3ae3ba9492..11cb1bb6d9e6e 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -106,6 +106,8 @@ pub(crate) struct CrateMetadata { private_dep: bool, /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`. host_hash: Option, + /// The crate was used non-speculatively. + used: bool, /// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext` /// and `ExpnId`). @@ -1811,6 +1813,7 @@ impl CrateMetadata { source: Lrc::new(source), private_dep, host_hash, + used: false, extern_crate: None, hygiene_context: Default::default(), def_key_cache: Default::default(), @@ -1860,6 +1863,10 @@ impl CrateMetadata { self.private_dep &= private_dep; } + pub(crate) fn used(&self) -> bool { + self.used + } + pub(crate) fn required_panic_strategy(&self) -> Option { self.root.required_panic_strategy } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0b352a02b64c7..7cd2f58779f84 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -26,6 +26,7 @@ use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; use std::any::Any; +use std::mem; use super::{Decodable, DecodeContext, DecodeIterator}; @@ -576,12 +577,24 @@ impl CStore { self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess) } + pub fn set_used_recursively(&mut self, cnum: CrateNum) { + let cmeta = self.get_crate_data_mut(cnum); + if !cmeta.used { + cmeta.used = true; + let dependencies = mem::take(&mut cmeta.dependencies); + for &dep_cnum in &dependencies { + self.set_used_recursively(dep_cnum); + } + self.get_crate_data_mut(cnum).dependencies = dependencies; + } + } + pub(crate) fn update_extern_crate(&mut self, cnum: CrateNum, extern_crate: ExternCrate) { let cmeta = self.get_crate_data_mut(cnum); if cmeta.update_extern_crate(extern_crate) { // Propagate the extern crate info to dependencies if it was updated. let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; - let dependencies = std::mem::take(&mut cmeta.dependencies); + let dependencies = mem::take(&mut cmeta.dependencies); for &dep_cnum in &dependencies { self.update_extern_crate(dep_cnum, extern_crate); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1f2803d4368ae..c020c134b770c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -23,6 +23,7 @@ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate}; +use rustc_metadata::creader::CStore; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; @@ -4541,14 +4542,20 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(res) = res && let Some(def_id) = res.opt_def_id() && !def_id.is_local() - && self.r.tcx.crate_types().contains(&CrateType::ProcMacro) - && matches!( - self.r.tcx.sess.opts.resolve_doc_links, - ResolveDocLinks::ExportedMetadata - ) { - // Encoding foreign def ids in proc macro crate metadata will ICE. - return None; + if self.r.tcx.crate_types().contains(&CrateType::ProcMacro) + && matches!( + self.r.tcx.sess.opts.resolve_doc_links, + ResolveDocLinks::ExportedMetadata + ) + { + // Encoding foreign def ids in proc macro crate metadata will ICE. + return None; + } + // Doc paths should be resolved speculatively and should not produce any + // diagnostics, but if they are indeed resolved, then we need to keep the + // corresponding crate alive. + CStore::from_tcx_mut(self.r.tcx).set_used_recursively(def_id.krate); } res }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9d09d060b59b8..6ca9236075b48 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1625,6 +1625,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.tcx .sess .time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate))); + self.crate_loader(|c| c.unload_unused_crates()); }); // Make sure we don't mutate the cstore from here on. diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 79efcc5d8b041..6ad3effe0e26e 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -1,11 +1,6 @@ error: extern location for std does not exist: -error: `#[panic_handler]` function required, but not found +error: requires `sized` lang_item -error: unwinding panics are not supported without std - | - = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding - = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors From d9cd0d4d1180f09ea67be012848ff295a4681961 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Feb 2024 16:01:54 +0000 Subject: [PATCH 602/676] Don't expect early-bound region to be local in RPITIT well-formedness --- compiler/rustc_middle/src/ty/context.rs | 2 +- .../in-trait/auxiliary/bad-region.rs | 7 +++++++ tests/ui/async-await/in-trait/bad-region.rs | 17 +++++++++++++++++ tests/ui/async-await/in-trait/bad-region.stderr | 14 ++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/ui/async-await/in-trait/auxiliary/bad-region.rs create mode 100644 tests/ui/async-await/in-trait/bad-region.rs create mode 100644 tests/ui/async-await/in-trait/bad-region.stderr diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0d53870a0baf0..70c6811e539b9 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1193,7 +1193,7 @@ impl<'tcx> TyCtxt<'tcx> { let (suitable_region_binding_scope, bound_region) = loop { let def_id = match region.kind() { ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?, - ty::ReEarlyParam(ebr) => ebr.def_id.expect_local(), + ty::ReEarlyParam(ebr) => ebr.def_id.as_local()?, _ => return None, // not a free region }; let scope = self.local_parent(def_id); diff --git a/tests/ui/async-await/in-trait/auxiliary/bad-region.rs b/tests/ui/async-await/in-trait/auxiliary/bad-region.rs new file mode 100644 index 0000000000000..02dc25aaa16bb --- /dev/null +++ b/tests/ui/async-await/in-trait/auxiliary/bad-region.rs @@ -0,0 +1,7 @@ +// edition:2021 + +#[allow(async_fn_in_trait)] + +pub trait BleRadio<'a> { + async fn transmit(&mut self); +} diff --git a/tests/ui/async-await/in-trait/bad-region.rs b/tests/ui/async-await/in-trait/bad-region.rs new file mode 100644 index 0000000000000..444368e21a497 --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-region.rs @@ -0,0 +1,17 @@ +// aux-build:bad-region.rs +// edition:2021 + +#![allow(async_fn_in_trait)] + +extern crate bad_region as jewel; + +use jewel::BleRadio; + +pub struct Radio {} + +impl BleRadio for Radio { +//~^ ERROR implicit elided lifetime not allowed here + async fn transmit(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/bad-region.stderr b/tests/ui/async-await/in-trait/bad-region.stderr new file mode 100644 index 0000000000000..9203fd790af78 --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-region.stderr @@ -0,0 +1,14 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/bad-region.rs:12:6 + | +LL | impl BleRadio for Radio { + | ^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | impl BleRadio<'_> for Radio { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0726`. From aef18c9bfb8c7844b95f6d950133f61b0fa2158b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Jan 2024 18:54:29 +0000 Subject: [PATCH 603/676] Mark "unused binding" suggestion as maybe incorrect Ignoring unused bindings should be a determination made by a human, `rustfix` shouldn't auto-apply the suggested change. Fix #54196. --- compiler/rustc_passes/src/errors.rs | 4 ++-- tests/ui/lint/future-incompat-json-test.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 77bfe57e3706f..5db2369ad76c2 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1739,7 +1739,7 @@ pub struct UnusedVariableTryPrefix { #[derive(Subdiagnostic)] pub enum UnusedVariableSugg { - #[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] + #[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")] TryPrefixSugg { #[suggestion_part(code = "_{name}")] spans: Vec, @@ -1778,7 +1778,7 @@ pub struct UnusedVarTryIgnore { } #[derive(Subdiagnostic)] -#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")] pub struct UnusedVarTryIgnoreSugg { #[suggestion_part(code = "{name}: _")] pub shorthands: Vec, diff --git a/tests/ui/lint/future-incompat-json-test.stderr b/tests/ui/lint/future-incompat-json-test.stderr index c4ab5a00d16cc..18fc3f17f0020 100644 --- a/tests/ui/lint/future-incompat-json-test.stderr +++ b/tests/ui/lint/future-incompat-json-test.stderr @@ -1,4 +1,4 @@ -{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`-A unused-variables` implied by `-A unused`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"to override `-A unused` add `#[allow(unused_variables)]`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` +{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`-A unused-variables` implied by `-A unused`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"to override `-A unused` add `#[allow(unused_variables)]`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` --> $DIR/future-incompat-json-test.rs:9:9 | LL | let x = 1; From f1308783b4a7e613d60bddfa0f5474363c198289 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Feb 2024 17:41:48 +0000 Subject: [PATCH 604/676] Make async closures test use async bound modifier --- .../async-closures/async-fn-mut-for-async-fn.rs | 6 ++---- .../async-closures/async-fn-once-for-async-fn.rs | 6 ++---- .../async-await/async-closures/auxiliary/block-on.rs | 2 +- tests/ui/async-await/async-closures/brand.rs | 5 ++--- tests/ui/async-await/async-closures/drop.rs | 6 ++---- tests/ui/async-await/async-closures/mangle.rs | 7 +++---- tests/ui/async-await/async-closures/wrong-fn-kind.rs | 8 +++----- .../ui/async-await/async-closures/wrong-fn-kind.stderr | 10 +++++----- 8 files changed, 20 insertions(+), 30 deletions(-) diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs index 8d7dc6a276b90..f73b43dd152f0 100644 --- a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs +++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs @@ -5,17 +5,15 @@ // FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. // ignore-pass (test emits codegen-time warnings) -#![feature(async_closure, async_fn_traits)] +#![feature(async_closure)] extern crate block_on; -use std::ops::AsyncFnMut; - fn main() { block_on::block_on(async { let x = async || {}; - async fn needs_async_fn_mut(mut x: impl AsyncFnMut()) { + async fn needs_async_fn_mut(mut x: impl async FnMut()) { x().await; } needs_async_fn_mut(x).await; diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs index 4afc43fe6bd92..0ba323a71cd13 100644 --- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs +++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs @@ -5,17 +5,15 @@ // FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. // ignore-pass (test emits codegen-time warnings) -#![feature(async_closure, async_fn_traits)] +#![feature(async_closure)] extern crate block_on; -use std::ops::AsyncFnOnce; - fn main() { block_on::block_on(async { let x = async || {}; - async fn needs_async_fn_once(x: impl AsyncFnOnce()) { + async fn needs_async_fn_once(x: impl async FnOnce()) { x().await; } needs_async_fn_once(x).await; diff --git a/tests/ui/async-await/async-closures/auxiliary/block-on.rs b/tests/ui/async-await/async-closures/auxiliary/block-on.rs index 3c27548b865a7..902e033cfe711 100644 --- a/tests/ui/async-await/async-closures/auxiliary/block-on.rs +++ b/tests/ui/async-await/async-closures/auxiliary/block-on.rs @@ -1,6 +1,6 @@ // edition: 2021 -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker)] use std::future::Future; use std::pin::pin; diff --git a/tests/ui/async-await/async-closures/brand.rs b/tests/ui/async-await/async-closures/brand.rs index 3bda7737bb406..26d2ed5a6ef65 100644 --- a/tests/ui/async-await/async-closures/brand.rs +++ b/tests/ui/async-await/async-closures/brand.rs @@ -2,19 +2,18 @@ // edition:2021 // build-pass -#![feature(async_closure, async_fn_traits)] +#![feature(async_closure)] extern crate block_on; use std::future::Future; use std::marker::PhantomData; -use std::ops::AsyncFn; struct S; struct B<'b>(PhantomData<&'b mut &'b mut ()>); impl S { - async fn q)>(self, f: F) { + async fn q)>(self, f: F) { f(B(PhantomData)).await; } } diff --git a/tests/ui/async-await/async-closures/drop.rs b/tests/ui/async-await/async-closures/drop.rs index 1b7f2f8a600d0..a243d20774d27 100644 --- a/tests/ui/async-await/async-closures/drop.rs +++ b/tests/ui/async-await/async-closures/drop.rs @@ -3,13 +3,11 @@ // run-pass // check-run-results -#![feature(async_closure, async_fn_traits)] +#![feature(async_closure)] #![allow(unused)] extern crate block_on; -use std::ops::AsyncFnOnce; - struct DropMe(i32); impl Drop for DropMe { @@ -18,7 +16,7 @@ impl Drop for DropMe { } } -async fn call_once(f: impl AsyncFnOnce()) { +async fn call_once(f: impl async FnOnce()) { println!("before call"); let fut = Box::pin(f()); println!("after call"); diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs index 98065c3c71109..9d231d551765e 100644 --- a/tests/ui/async-await/async-closures/mangle.rs +++ b/tests/ui/async-await/async-closures/mangle.rs @@ -8,20 +8,19 @@ // FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. // ignore-pass (test emits codegen-time warnings) -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker)] extern crate block_on; use std::future::Future; -use std::ops::{AsyncFnMut, AsyncFnOnce}; use std::pin::pin; use std::task::*; -async fn call_mut(f: &mut impl AsyncFnMut()) { +async fn call_mut(f: &mut impl async FnMut()) { f().await; } -async fn call_once(f: impl AsyncFnOnce()) { +async fn call_once(f: impl async FnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs index 248288325319e..f86cee3e0709e 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs @@ -2,17 +2,15 @@ // FIXME(async_closures): This needs a better error message! -#![feature(async_closure, async_fn_traits)] - -use std::ops::AsyncFn; +#![feature(async_closure)] fn main() { - fn needs_async_fn(_: impl AsyncFn()) {} + fn needs_async_fn(_: impl async Fn()) {} let mut x = 1; needs_async_fn(async || { //~^ ERROR i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper - // FIXME: Should say "closure is AsyncFnMut but it needs AsyncFn" or sth. + // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth. x += 1; }); } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr index ef95e6a211c74..4ef8484cc34cd 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -1,21 +1,21 @@ error[E0277]: the trait bound `i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper` is not satisfied - --> $DIR/wrong-fn-kind.rs:13:20 + --> $DIR/wrong-fn-kind.rs:11:20 | LL | needs_async_fn(async || { | _____--------------_^ | | | | | required by a bound introduced by this call LL | | -LL | | // FIXME: Should say "closure is AsyncFnMut but it needs AsyncFn" or sth. +LL | | // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth. LL | | x += 1; LL | | }); | |_____^ the trait `ops::async_function::internal_implementation_detail::AsyncFnKindHelper` is not implemented for `i16` | note: required by a bound in `needs_async_fn` - --> $DIR/wrong-fn-kind.rs:10:31 + --> $DIR/wrong-fn-kind.rs:8:31 | -LL | fn needs_async_fn(_: impl AsyncFn()) {} - | ^^^^^^^^^ required by this bound in `needs_async_fn` +LL | fn needs_async_fn(_: impl async Fn()) {} + | ^^^^^^^^^^ required by this bound in `needs_async_fn` error: aborting due to 1 previous error From 8d1c20a539b72abdbe1ede872f19e0a1a6f34be4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 6 Feb 2024 17:13:32 +1100 Subject: [PATCH 605/676] Remove return value from `emit_stashed_diagnostics`. It's never used. --- compiler/rustc_errors/src/lib.rs | 9 +++------ compiler/rustc_session/src/session.rs | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a4112d717d029..7c62e3aa42281 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -708,7 +708,7 @@ impl DiagCtxt { } /// Emit all stashed diagnostics. - pub fn emit_stashed_diagnostics(&self) -> Option { + pub fn emit_stashed_diagnostics(&self) { self.inner.borrow_mut().emit_stashed_diagnostics() } @@ -1216,9 +1216,8 @@ impl DiagCtxt { // `DiagCtxtInner::foo`. impl DiagCtxtInner { /// Emit all stashed diagnostics. - fn emit_stashed_diagnostics(&mut self) -> Option { + fn emit_stashed_diagnostics(&mut self) { let has_errors = self.has_errors(); - let mut reported = None; 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() { @@ -1235,10 +1234,8 @@ impl DiagCtxtInner { continue; } } - let reported_this = self.emit_diagnostic(diag); - reported = reported.or(reported_this); + self.emit_diagnostic(diag); } - reported } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f6af5a4f87e07..ec14385f40c62 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -315,7 +315,7 @@ impl Session { pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> { // We must include lint errors here. if let Some(reported) = self.dcx().has_errors_or_lint_errors() { - let _ = self.dcx().emit_stashed_diagnostics(); + self.dcx().emit_stashed_diagnostics(); Err(reported) } else { Ok(()) From 14dda5fdfb81e61b2acc85f27609f879aeaa166d Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 6 Feb 2024 21:03:07 -0500 Subject: [PATCH 606/676] Don't use bashism in checktools.sh --- src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index cc0c658aabd2b..f5c426a717f78 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -30,7 +30,7 @@ python3 "$X_PY" test --stage 2 src/tools/rustfmt # We set the GC interval to the shortest possible value (0 would be off) to increase the chance # that bugs which only surface when the GC runs at a specific time are more likely to cause CI to fail. # This significantly increases the runtime of our test suite, or we'd do this in PR CI too. -if [[ -z "${PR_CI_JOB:-}" ]]; then +if [ -z "${PR_CI_JOB:-}" ]; then MIRIFLAGS=-Zmiri-provenance-gc=1 python3 "$X_PY" test --stage 2 src/tools/miri else python3 "$X_PY" test --stage 2 src/tools/miri From 40878ca6ea79d6e55e430846a2de3350a76cd08f Mon Sep 17 00:00:00 2001 From: r0cky Date: Tue, 2 Jan 2024 00:14:21 +0800 Subject: [PATCH 607/676] Make traits / trait methods detected by the dead code lint! --- compiler/rustc_passes/src/dead.rs | 91 +++++++++++++++++----- tests/ui/lint/dead-code/issue-41883.rs | 29 +++++++ tests/ui/lint/dead-code/issue-41883.stderr | 36 +++++++++ 3 files changed, 136 insertions(+), 20 deletions(-) create mode 100644 tests/ui/lint/dead-code/issue-41883.rs create mode 100644 tests/ui/lint/dead-code/issue-41883.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d19987cb33cf2..e11102c459e42 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -4,6 +4,7 @@ // is dead. use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; +use hir::ItemKind; use rustc_data_structures::unord::UnordSet; use rustc_errors::MultiSpan; use rustc_hir as hir; @@ -14,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; use rustc_span::symbol::{sym, Symbol}; @@ -381,9 +382,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_item(self, item) } hir::ItemKind::ForeignMod { .. } => {} + hir::ItemKind::Trait(..) => { + for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) { + if let Some(local_def_id) = impl_def_id.as_local() + && let ItemKind::Impl(impl_ref) = + self.tcx.hir().expect_item(local_def_id).kind + { + // skip items + // mark dependent traits live + intravisit::walk_generics(self, impl_ref.generics); + // mark dependent parameters live + intravisit::walk_path(self, impl_ref.of_trait.unwrap().path); + } + } + + intravisit::walk_item(self, item) + } _ => intravisit::walk_item(self, item), }, Node::TraitItem(trait_item) => { + // mark corresponing ImplTerm live + let trait_item_id = trait_item.owner_id.to_def_id(); + if let Some(trait_id) = self.tcx.trait_of_item(trait_item_id) { + // mark the trait live + self.check_def_id(trait_id); + + for impl_id in self.tcx.all_impls(trait_id) { + if let Some(local_impl_id) = impl_id.as_local() + && let ItemKind::Impl(impl_ref) = + self.tcx.hir().expect_item(local_impl_id).kind + { + // mark self_ty live + intravisit::walk_ty(self, impl_ref.self_ty); + if let Some(&impl_item_id) = + self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id) + { + self.check_def_id(impl_item_id); + } + } + } + } intravisit::walk_trait_item(self, trait_item); } Node::ImplItem(impl_item) => { @@ -636,10 +674,6 @@ fn check_item<'tcx>( } } DefKind::Impl { of_trait } => { - if of_trait { - worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No)); - } - // get DefIds from another query let local_def_ids = tcx .associated_item_def_ids(id.owner_id) @@ -648,7 +682,11 @@ fn check_item<'tcx>( // And we access the Map here to get HirId from LocalDefId for id in local_def_ids { - if of_trait { + // for impl trait blocks, mark associate functions live if the trait is public + if of_trait + && (!matches!(tcx.def_kind(id), DefKind::AssocFn) + || tcx.local_visibility(id) == Visibility::Public) + { worklist.push((id, ComesFromAllowExpect::No)); } else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id) { worklist.push((id, comes_from_allow)); @@ -679,7 +717,7 @@ fn check_trait_item( use hir::TraitItemKind::{Const, Fn}; if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { let trait_item = tcx.hir().trait_item(id); - if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) + if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..)) && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) { @@ -948,7 +986,8 @@ impl<'tcx> DeadVisitor<'tcx> { | DefKind::TyAlias | DefKind::Enum | DefKind::Union - | DefKind::ForeignTy => self.warn_dead_code(def_id, "used"), + | DefKind::ForeignTy + | DefKind::Trait => self.warn_dead_code(def_id, "used"), DefKind::Struct => self.warn_dead_code(def_id, "constructed"), DefKind::Variant | DefKind::Field => bug!("should be handled specially"), _ => {} @@ -973,18 +1012,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { let module_items = tcx.hir_module_items(module); for item in module_items.items() { - if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind { - let mut dead_items = Vec::new(); - for item in impl_item.items { - let def_id = item.id.owner_id.def_id; - if !visitor.is_live_code(def_id) { - let name = tcx.item_name(def_id.to_def_id()); - let level = visitor.def_lint_level(def_id); + let def_kind = tcx.def_kind(item.owner_id); - dead_items.push(DeadItem { def_id, name, level }) + let mut dead_codes = Vec::new(); + // if we have diagnosed the trait, do not diagnose unused methods + if matches!(def_kind, DefKind::Impl { .. }) + || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) + { + for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { + // We have diagnosed unused methods in traits + if matches!(def_kind, DefKind::Impl { of_trait: true }) + && tcx.def_kind(def_id) == DefKind::AssocFn + || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn + { + continue; + } + + if let Some(local_def_id) = def_id.as_local() + && !visitor.is_live_code(local_def_id) + { + let name = tcx.item_name(def_id); + let level = visitor.def_lint_level(local_def_id); + dead_codes.push(DeadItem { def_id: local_def_id, name, level }); } } - visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, ReportOn::NamedField); + } + if !dead_codes.is_empty() { + visitor.warn_multiple(item.owner_id.def_id, "used", dead_codes, ReportOn::NamedField); } if !live_symbols.contains(&item.owner_id.def_id) { @@ -997,7 +1051,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { continue; } - let def_kind = tcx.def_kind(item.owner_id); if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind { let adt = tcx.adt_def(item.owner_id); let mut dead_variants = Vec::new(); @@ -1044,8 +1097,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { for foreign_item in module_items.foreign_items() { visitor.check_definition(foreign_item.owner_id.def_id); } - - // We do not warn trait items. } pub(crate) fn provide(providers: &mut Providers) { diff --git a/tests/ui/lint/dead-code/issue-41883.rs b/tests/ui/lint/dead-code/issue-41883.rs new file mode 100644 index 0000000000000..e165861e893e0 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-41883.rs @@ -0,0 +1,29 @@ +#![deny(dead_code)] + +enum Category { + Dead, //~ ERROR variant `Dead` is never constructed + Used, +} + +trait UnusedTrait { //~ ERROR trait `UnusedTrait` is never used + fn this_is_unused(&self) -> Category { + Category::Dead + } +} + +struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed + +impl UnusedTrait for UnusedStruct { + fn this_is_unused(&self) -> Category { + Category::Used + } +} + +mod private { + #[derive(Debug)] + struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed +} + +fn main() { + let _c = Category::Used; +} diff --git a/tests/ui/lint/dead-code/issue-41883.stderr b/tests/ui/lint/dead-code/issue-41883.stderr new file mode 100644 index 0000000000000..cf079e4dda33a --- /dev/null +++ b/tests/ui/lint/dead-code/issue-41883.stderr @@ -0,0 +1,36 @@ +error: variant `Dead` is never constructed + --> $DIR/issue-41883.rs:4:5 + | +LL | enum Category { + | -------- variant in this enum +LL | Dead, + | ^^^^ + | +note: the lint level is defined here + --> $DIR/issue-41883.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: trait `UnusedTrait` is never used + --> $DIR/issue-41883.rs:8:7 + | +LL | trait UnusedTrait { + | ^^^^^^^^^^^ + +error: struct `UnusedStruct` is never constructed + --> $DIR/issue-41883.rs:14:8 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + +error: struct `UnusedStruct` is never constructed + --> $DIR/issue-41883.rs:24:12 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + | + = note: `UnusedStruct` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis + +error: aborting due to 4 previous errors + From c7519d42c2664828c98fdb98acab73e9a39b0b97 Mon Sep 17 00:00:00 2001 From: r0cky Date: Wed, 7 Feb 2024 10:42:01 +0800 Subject: [PATCH 608/676] Update tests --- compiler/rustc_span/src/source_map/tests.rs | 49 +------------------ library/core/tests/macros.rs | 1 + library/std/src/sys_common/mod.rs | 2 + .../tests/fail/dyn-call-trait-mismatch.rs | 1 + .../tests/fail/dyn-upcast-trait-mismatch.rs | 6 +++ .../tests/pass/cast-rfc0401-vtable-kinds.rs | 1 + src/tools/miri/tests/pass/dyn-upcast.rs | 3 ++ src/tools/miri/tests/pass/weak_memory/weak.rs | 1 + src/tools/tidy/src/ui_tests.rs | 5 +- .../instantiation-through-vtable.rs | 4 +- .../trait-method-default-impl.rs | 3 ++ .../codegen-units/item-collection/unsizing.rs | 2 + tests/ui-fulldeps/rustc_encodable_hygiene.rs | 2 +- .../anon-params/anon-params-deprecated.fixed | 1 + .../ui/anon-params/anon-params-deprecated.rs | 1 + .../anon-params/anon-params-deprecated.stderr | 6 +-- .../associated-const-outer-ty-refs.rs | 3 +- .../associated-const-type-parameters.rs | 2 +- .../associated-const-type-parameters.stderr | 10 ++++ .../dyn-impl-trait-type.rs | 2 +- .../dyn-impl-trait-type.stderr | 12 +++++ .../dyn-rpit-and-let.rs | 2 +- .../dyn-rpit-and-let.stderr | 12 +++++ tests/ui/associated-type-bounds/rpit.rs | 2 +- tests/ui/associated-type-bounds/rpit.stderr | 12 +++++ ...ng-assoc-type-because-of-assoc-const.fixed | 1 + ...ining-assoc-type-because-of-assoc-const.rs | 1 + ...g-assoc-type-because-of-assoc-const.stderr | 2 +- .../trait-alias-impl-trait.rs | 1 + .../associated-types-for-unimpl-trait.fixed | 1 + .../associated-types-for-unimpl-trait.rs | 1 + .../associated-types-for-unimpl-trait.stderr | 2 +- .../associated-types-in-bound-type-arg.rs | 2 +- .../associated-types-issue-20220.rs | 2 +- .../associated-types-issue-20220.stderr | 10 ++++ .../associated-types-issue-20371.rs | 2 +- .../associated-types-nested-projections.rs | 2 +- ...associated-types-nested-projections.stderr | 13 +++++ ...sociated-types-normalize-in-bounds-ufcs.rs | 2 +- .../associated-types-normalize-in-bounds.rs | 2 +- ...d-types-projection-bound-in-supertraits.rs | 2 +- ...ypes-projection-from-known-type-in-impl.rs | 2 +- ...-projection-from-known-type-in-impl.stderr | 13 +++++ ...ated-trait-in-method-without-default.fixed | 1 + ...related-trait-in-method-without-default.rs | 1 + ...ted-trait-in-method-without-default.stderr | 2 +- ...ted-types-projection-to-unrelated-trait.rs | 2 +- ...ed-path-with-trait-with-type-parameters.rs | 2 +- .../associated-types-resolve-lifetime.rs | 2 +- .../ui/associated-types/impl-wf-cycle-5.fixed | 2 + tests/ui/associated-types/impl-wf-cycle-5.rs | 2 + .../associated-types/impl-wf-cycle-5.stderr | 4 +- .../ui/associated-types/impl-wf-cycle-6.fixed | 2 + tests/ui/associated-types/impl-wf-cycle-6.rs | 2 + .../associated-types/impl-wf-cycle-6.stderr | 4 +- .../auto-traits/auto-trait-validation.fixed | 1 + tests/ui/auto-traits/auto-trait-validation.rs | 1 + .../auto-traits/auto-trait-validation.stderr | 8 +-- tests/ui/auto-traits/auto-traits.rs | 4 +- tests/ui/auto-traits/auto-traits.stderr | 16 ++++++ .../builtin-superkinds-in-metadata2.rs | 2 +- .../builtin-superkinds-simple2.rs | 2 +- .../builtin-superkinds-typaram.rs | 2 +- tests/ui/cast/cast-rfc0401-vtable-kinds.rs | 2 +- .../ui/cast/cast-rfc0401-vtable-kinds.stderr | 10 ++++ tests/ui/cast/fat-ptr-cast-rpass.rs | 2 +- tests/ui/cast/fat-ptr-cast-rpass.stderr | 12 +++++ tests/ui/coercion/issue-14589.rs | 2 +- tests/ui/coercion/issue-14589.stderr | 12 +++++ .../coherence-multidispatch-tuple.rs | 2 +- .../const-generics/associated-type-bound.rs | 2 +- .../condition-in-trait-const-arg.rs | 2 +- tests/ui/const-generics/dyn-supertraits.rs | 6 +-- .../ui/const-generics/dyn-supertraits.stderr | 22 +++++++++ .../issues/issue-69654-run-pass.rs | 2 +- .../issues/issue-69654-run-pass.stderr | 10 ++++ tests/ui/consts/const-block-item.rs | 2 +- tests/ui/consts/const-block-item.stderr | 10 ++++ tests/ui/consts/underscore_const_names.rs | 4 +- tests/ui/default-method-parsing.rs | 2 +- tests/ui/delegation/target-expr-pass.rs | 6 +-- tests/ui/delegation/target-expr-pass.stderr | 22 ++++++++- tests/ui/deriving/deriving-bounds.rs | 2 +- tests/ui/drop/drop-struct-as-object.rs | 2 +- tests/ui/drop/drop-struct-as-object.stderr | 12 +++++ .../dynamically-sized-types/dst-coercions.rs | 2 +- .../dst-coercions.stderr | 12 +++++ tests/ui/empty-type-parameter-list.rs | 2 +- tests/ui/empty-type-parameter-list.stderr | 10 ++++ .../explicit-call-to-supertrait-dtor.fixed | 1 + .../explicit-call-to-supertrait-dtor.rs | 1 + .../explicit-call-to-supertrait-dtor.stderr | 2 +- tests/ui/extern/no-mangle-associated-fn.rs | 2 +- .../ui/extern/no-mangle-associated-fn.stderr | 10 ++++ .../issue-88360.fixed | 1 + .../generic-associated-types/issue-88360.rs | 1 + .../issue-88360.stderr | 2 +- tests/ui/generics/generic-no-mangle.fixed | 2 +- tests/ui/generics/generic-no-mangle.rs | 2 +- tests/ui/impl-trait/example-st.rs | 2 +- tests/ui/impl-trait/example-st.stderr | 10 ++++ .../in-trait/suggest-missing-item.fixed | 1 + .../in-trait/suggest-missing-item.rs | 1 + .../in-trait/suggest-missing-item.stderr | 2 +- .../ui/impl-trait/type-alias-generic-param.rs | 2 +- .../type-alias-generic-param.stderr | 10 ++++ tests/ui/issues/issue-14399.rs | 2 +- tests/ui/issues/issue-14399.stderr | 12 +++++ tests/ui/issues/issue-15858.rs | 2 +- tests/ui/issues/issue-15858.stderr | 12 +++++ tests/ui/issues/issue-17351.rs | 2 +- tests/ui/issues/issue-17351.stderr | 12 +++++ tests/ui/issues/issue-18173.rs | 2 +- tests/ui/issues/issue-20055-box-trait.rs | 2 +- tests/ui/issues/issue-20055-box-trait.stderr | 12 +++++ tests/ui/issues/issue-21909.rs | 2 +- tests/ui/issues/issue-23485.rs | 2 +- tests/ui/issues/issue-23485.stderr | 13 +++++ tests/ui/issues/issue-2989.rs | 4 +- tests/ui/issues/issue-2989.stderr | 10 ++++ tests/ui/issues/issue-34074.rs | 2 +- tests/ui/issues/issue-34503.rs | 2 +- tests/ui/issues/issue-34503.stderr | 14 ++++++ tests/ui/issues/issue-3563-3.rs | 2 +- tests/ui/issues/issue-3563-3.stderr | 13 +++++ tests/ui/issues/issue-50571.fixed | 1 + tests/ui/issues/issue-50571.rs | 1 + tests/ui/issues/issue-50571.stderr | 2 +- tests/ui/issues/issue-7575.rs | 2 +- tests/ui/issues/issue-7575.stderr | 10 ++++ tests/ui/issues/issue-7911.rs | 2 +- tests/ui/issues/issue-7911.stderr | 12 +++++ tests/ui/issues/issue-8248.rs | 2 +- tests/ui/issues/issue-8248.stderr | 12 +++++ tests/ui/issues/issue-9951.rs | 2 +- tests/ui/issues/issue-9951.stderr | 12 +++++ tests/ui/lint/dead-code/associated-type.rs | 2 +- .../multiple-dead-codes-in-the-same-struct.rs | 2 +- ...tiple-dead-codes-in-the-same-struct.stderr | 12 ++--- tests/ui/lint/issue-20343.rs | 3 ++ tests/ui/macros/issue-22463.rs | 2 +- tests/ui/methods/method-lookup-order.rs | 1 + .../methods/method-recursive-blanket-impl.rs | 2 +- .../method-recursive-blanket-impl.stderr | 10 ++++ .../method-two-trait-defer-resolution-2.rs | 2 +- ...method-two-trait-defer-resolution-2.stderr | 12 +++++ ...o-traits-distinguished-via-where-clause.rs | 2 +- ...aits-distinguished-via-where-clause.stderr | 10 ++++ tests/ui/mir/mir_raw_fat_ptr.rs | 2 +- tests/ui/mir/mir_raw_fat_ptr.stderr | 12 +++++ .../ui/moves/issue-22536-copy-mustnt-zero.rs | 2 +- .../moves/issue-22536-copy-mustnt-zero.stderr | 13 +++++ .../assoc_type_bounds_implicit_sized.fixed | 1 + .../assoc_type_bounds_implicit_sized.rs | 1 + .../assoc_type_bounds_implicit_sized.stderr | 4 +- tests/ui/overloaded/issue-14958.rs | 2 +- tests/ui/overloaded/issue-14958.stderr | 12 +++++ .../overloaded/overloaded-index-in-field.rs | 2 +- .../overloaded-index-in-field.stderr | 15 ++++++ tests/ui/parser/parse-assoc-type-lt.rs | 2 +- tests/ui/parser/suggest-assoc-const.fixed | 1 + tests/ui/parser/suggest-assoc-const.rs | 1 + tests/ui/parser/suggest-assoc-const.stderr | 2 +- ...ing-semicolon-after-impl-trait-items.fixed | 1 + ...moving-semicolon-after-impl-trait-items.rs | 1 + ...ng-semicolon-after-impl-trait-items.stderr | 2 +- tests/ui/pattern/issue-22546.rs | 2 +- tests/ui/pattern/issue-22546.stderr | 10 ++++ .../sealed-traits/re-exported-trait.fixed | 1 + .../sealed-traits/re-exported-trait.rs | 1 + .../sealed-traits/re-exported-trait.stderr | 4 +- ...est-fix-invalid-top-level-macro-attr.fixed | 1 + ...uggest-fix-invalid-top-level-macro-attr.rs | 1 + ...st-fix-invalid-top-level-macro-attr.stderr | 1 + .../regions-no-variance-from-fn-generics.rs | 2 +- ...lid-unused-qualifications-suggestion.fixed | 1 + ...nvalid-unused-qualifications-suggestion.rs | 1 + ...id-unused-qualifications-suggestion.stderr | 6 +-- ...al-self-impl-for-unsafe-obj.current.stderr | 15 ++++++ ...anual-self-impl-for-unsafe-obj.next.stderr | 15 ++++++ .../manual-self-impl-for-unsafe-obj.rs | 2 +- tests/ui/rust-2018/issue-51008-1.rs | 2 +- tests/ui/rust-2018/issue-51008.rs | 2 +- tests/ui/sized/coinductive-2.rs | 2 +- tests/ui/sized/coinductive-2.stderr | 10 ++++ .../ui/specialization/assoc-ty-graph-cycle.rs | 2 +- .../defaultimpl/out-of-order.rs | 2 +- .../defaultimpl/overlap-projection.rs | 2 +- .../specialization-out-of-order.rs | 2 +- .../specialization-overlap-projection.rs | 2 +- .../specialization-supertraits.rs | 2 +- tests/ui/statics/static-impl.rs | 2 +- tests/ui/statics/static-impl.stderr | 13 +++++ tests/ui/stdlib-unit-tests/raw-fat-ptr.rs | 2 +- tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr | 12 +++++ .../ui/structs-enums/enum-null-pointer-opt.rs | 2 +- .../enum-null-pointer-opt.stderr | 12 +++++ tests/ui/suggestions/bound-suggestions.fixed | 5 ++ tests/ui/suggestions/bound-suggestions.rs | 5 ++ tests/ui/suggestions/bound-suggestions.stderr | 10 ++-- tests/ui/suggestions/constrain-trait.fixed | 1 + tests/ui/suggestions/constrain-trait.rs | 1 + tests/ui/suggestions/constrain-trait.stderr | 4 +- .../lifetimes/type-param-bound-scope.fixed | 1 + .../lifetimes/type-param-bound-scope.rs | 1 + .../lifetimes/type-param-bound-scope.stderr | 10 ++-- .../missing-bound-in-manual-copy-impl-2.fixed | 1 + .../missing-bound-in-manual-copy-impl-2.rs | 1 + ...missing-bound-in-manual-copy-impl-2.stderr | 4 +- .../missing-bound-in-manual-copy-impl.fixed | 1 + .../missing-bound-in-manual-copy-impl.rs | 1 + .../missing-bound-in-manual-copy-impl.stderr | 2 +- tests/ui/suggestions/missing-trait-item.fixed | 1 + tests/ui/suggestions/missing-trait-item.rs | 1 + .../ui/suggestions/missing-trait-item.stderr | 4 +- .../ui/threads-sendsync/sync-send-atomics.rs | 2 +- tests/ui/traits/alias/bounds.rs | 2 +- tests/ui/traits/alias/bounds.stderr | 10 ++++ tests/ui/traits/alias/syntax.rs | 2 +- .../bound/impl-comparison-duplicates.rs | 2 +- tests/ui/traits/bound/recursion.rs | 2 +- tests/ui/traits/composition-trivial.rs | 2 +- tests/ui/traits/cycle-generic-bound.rs | 2 +- .../ui/traits/default-method/bound-subst4.rs | 2 +- .../traits/default-method/bound-subst4.stderr | 13 +++++ tests/ui/traits/default-method/mut.rs | 2 +- .../traits/impl-inherent-prefer-over-trait.rs | 2 +- .../impl-inherent-prefer-over-trait.stderr | 12 +++++ .../traits/impl-object-overlap-issue-23853.rs | 2 +- .../impl-object-overlap-issue-23853.stderr | 12 +++++ tests/ui/traits/impl.rs | 2 +- tests/ui/traits/impl.stderr | 12 +++++ tests/ui/traits/issue-38033.rs | 2 +- tests/ui/traits/issue-38033.stderr | 13 +++++ tests/ui/traits/issue-56488.rs | 2 +- tests/ui/traits/issue-59029-2.rs | 2 +- tests/ui/traits/issue-6128.rs | 2 +- tests/ui/traits/issue-6128.stderr | 14 ++++++ ...ispatch-conditional-impl-not-considered.rs | 2 +- ...tch-conditional-impl-not-considered.stderr | 10 ++++ .../multidispatch-infer-convert-target.rs | 2 +- .../multidispatch-infer-convert-target.stderr | 12 +++++ .../negative-specializes-negative.rs | 2 +- tests/ui/traits/trait-upcasting/lifetime.rs | 4 +- .../ui/traits/trait-upcasting/lifetime.stderr | 25 ++++++++++ .../ui/traits/trait-upcasting/replace-vptr.rs | 4 +- .../trait-upcasting/replace-vptr.stderr | 20 ++++++++ tests/ui/traits/use-before-def.rs | 2 +- tests/ui/traits/wf-object/reverse-order.rs | 2 +- tests/ui/trivial_casts-rpass.rs | 2 +- tests/ui/trivial_casts-rpass.stderr | 12 +++++ tests/ui/type-alias-impl-trait/issue-58887.rs | 2 +- ...use-inherent-impl-ampersand-rust2015.fixed | 1 + ...clause-inherent-impl-ampersand-rust2015.rs | 1 + ...se-inherent-impl-ampersand-rust2015.stderr | 2 +- ...use-inherent-impl-ampersand-rust2018.fixed | 1 + ...clause-inherent-impl-ampersand-rust2018.rs | 1 + ...se-inherent-impl-ampersand-rust2018.stderr | 2 +- .../where-clause-trait-impl-region-2015.fixed | 1 + .../where-clause-trait-impl-region-2015.rs | 1 + ...where-clause-trait-impl-region-2015.stderr | 2 +- .../where-clause-trait-impl-region-2018.fixed | 2 + .../where-clause-trait-impl-region-2018.rs | 2 + ...where-clause-trait-impl-region-2018.stderr | 2 +- tests/ui/where-clauses/issue-50825-1.rs | 2 +- .../where-clause-bounds-inconsistency.rs | 2 +- .../where-clause-early-bound-lifetimes.rs | 2 +- .../where-clause-early-bound-lifetimes.stderr | 12 +++++ .../where-clause-method-substituion-rpass.rs | 2 +- ...ere-clause-method-substituion-rpass.stderr | 12 +++++ ...-clause-placement-assoc-type-in-impl.fixed | 2 + ...ere-clause-placement-assoc-type-in-impl.rs | 2 + ...clause-placement-assoc-type-in-impl.stderr | 6 +-- ...clause-placement-assoc-type-in-trait.fixed | 1 + ...re-clause-placement-assoc-type-in-trait.rs | 1 + ...lause-placement-assoc-type-in-trait.stderr | 4 +- 276 files changed, 1049 insertions(+), 234 deletions(-) create mode 100644 tests/ui/associated-consts/associated-const-type-parameters.stderr create mode 100644 tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr create mode 100644 tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr create mode 100644 tests/ui/associated-type-bounds/rpit.stderr create mode 100644 tests/ui/associated-types/associated-types-issue-20220.stderr create mode 100644 tests/ui/associated-types/associated-types-nested-projections.stderr create mode 100644 tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr create mode 100644 tests/ui/auto-traits/auto-traits.stderr create mode 100644 tests/ui/cast/cast-rfc0401-vtable-kinds.stderr create mode 100644 tests/ui/cast/fat-ptr-cast-rpass.stderr create mode 100644 tests/ui/coercion/issue-14589.stderr create mode 100644 tests/ui/const-generics/dyn-supertraits.stderr create mode 100644 tests/ui/const-generics/issues/issue-69654-run-pass.stderr create mode 100644 tests/ui/consts/const-block-item.stderr create mode 100644 tests/ui/drop/drop-struct-as-object.stderr create mode 100644 tests/ui/dynamically-sized-types/dst-coercions.stderr create mode 100644 tests/ui/empty-type-parameter-list.stderr create mode 100644 tests/ui/extern/no-mangle-associated-fn.stderr create mode 100644 tests/ui/impl-trait/example-st.stderr create mode 100644 tests/ui/impl-trait/type-alias-generic-param.stderr create mode 100644 tests/ui/issues/issue-14399.stderr create mode 100644 tests/ui/issues/issue-15858.stderr create mode 100644 tests/ui/issues/issue-17351.stderr create mode 100644 tests/ui/issues/issue-20055-box-trait.stderr create mode 100644 tests/ui/issues/issue-23485.stderr create mode 100644 tests/ui/issues/issue-2989.stderr create mode 100644 tests/ui/issues/issue-34503.stderr create mode 100644 tests/ui/issues/issue-3563-3.stderr create mode 100644 tests/ui/issues/issue-7575.stderr create mode 100644 tests/ui/issues/issue-7911.stderr create mode 100644 tests/ui/issues/issue-8248.stderr create mode 100644 tests/ui/issues/issue-9951.stderr create mode 100644 tests/ui/methods/method-recursive-blanket-impl.stderr create mode 100644 tests/ui/methods/method-two-trait-defer-resolution-2.stderr create mode 100644 tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr create mode 100644 tests/ui/mir/mir_raw_fat_ptr.stderr create mode 100644 tests/ui/moves/issue-22536-copy-mustnt-zero.stderr create mode 100644 tests/ui/overloaded/issue-14958.stderr create mode 100644 tests/ui/overloaded/overloaded-index-in-field.stderr create mode 100644 tests/ui/pattern/issue-22546.stderr create mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr create mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr create mode 100644 tests/ui/sized/coinductive-2.stderr create mode 100644 tests/ui/statics/static-impl.stderr create mode 100644 tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr create mode 100644 tests/ui/structs-enums/enum-null-pointer-opt.stderr create mode 100644 tests/ui/traits/alias/bounds.stderr create mode 100644 tests/ui/traits/default-method/bound-subst4.stderr create mode 100644 tests/ui/traits/impl-inherent-prefer-over-trait.stderr create mode 100644 tests/ui/traits/impl-object-overlap-issue-23853.stderr create mode 100644 tests/ui/traits/impl.stderr create mode 100644 tests/ui/traits/issue-38033.stderr create mode 100644 tests/ui/traits/issue-6128.stderr create mode 100644 tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr create mode 100644 tests/ui/traits/multidispatch-infer-convert-target.stderr create mode 100644 tests/ui/traits/trait-upcasting/lifetime.stderr create mode 100644 tests/ui/traits/trait-upcasting/replace-vptr.stderr create mode 100644 tests/ui/trivial_casts-rpass.stderr create mode 100644 tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr create mode 100644 tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 5788d11ed43ca..51f8aa04e8a7f 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -1,5 +1,7 @@ use super::*; +use rustc_data_structures::sync::FreezeLock; + fn init_source_map() -> SourceMap { let sm = SourceMap::new(FilePathMapping::empty()); sm.new_source_file(PathBuf::from("blork.rs").into(), "first line.\nsecond line".to_string()); @@ -263,53 +265,6 @@ fn t10() { ); } -/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`. -trait SourceMapExtension { - fn span_substr( - &self, - file: &Lrc, - source_text: &str, - substring: &str, - n: usize, - ) -> Span; -} - -impl SourceMapExtension for SourceMap { - fn span_substr( - &self, - file: &Lrc, - source_text: &str, - substring: &str, - n: usize, - ) -> Span { - eprintln!( - "span_substr(file={:?}/{:?}, substring={:?}, n={})", - file.name, file.start_pos, substring, n - ); - let mut i = 0; - let mut hi = 0; - loop { - let offset = source_text[hi..].find(substring).unwrap_or_else(|| { - panic!( - "source_text `{}` does not have {} occurrences of `{}`, only {}", - source_text, n, substring, i - ); - }); - let lo = hi + offset; - hi = lo + substring.len(); - if i == n { - let span = Span::with_root_ctxt( - BytePos(lo as u32 + file.start_pos.0), - BytePos(hi as u32 + file.start_pos.0), - ); - assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring); - return span; - } - i += 1; - } - } -} - // Takes a unix-style path and returns a platform specific path. fn path(p: &str) -> PathBuf { path_str(p).into() diff --git a/library/core/tests/macros.rs b/library/core/tests/macros.rs index eb886def164ac..09994fbcbdb78 100644 --- a/library/core/tests/macros.rs +++ b/library/core/tests/macros.rs @@ -1,3 +1,4 @@ +#[allow(dead_code)] trait Trait { fn blah(&self); } diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 851832a377cf8..01f83ecb41452 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -59,12 +59,14 @@ cfg_if::cfg_if! { /// A trait for viewing representations from std types #[doc(hidden)] +#[allow(dead_code)] // not used on all platforms pub trait AsInner { fn as_inner(&self) -> &Inner; } /// A trait for viewing representations from std types #[doc(hidden)] +#[allow(dead_code)] // not used on all platforms pub trait AsInnerMut { fn as_inner_mut(&mut self) -> &mut Inner; } diff --git a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs index 0e7c3dbcc040f..13f913454dcdf 100644 --- a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs +++ b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs @@ -1,4 +1,5 @@ trait T1 { + #[allow(dead_code)] fn method1(self: Box); } trait T2 { diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs index 648ac07c43ec9..982f33b0a3102 100644 --- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs +++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs @@ -2,30 +2,36 @@ #![allow(incomplete_features)] trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + #[allow(dead_code)] fn a(&self) -> i32 { 10 } + #[allow(dead_code)] fn z(&self) -> i32 { 11 } + #[allow(dead_code)] fn y(&self) -> i32 { 12 } } trait Bar: Foo { + #[allow(dead_code)] fn b(&self) -> i32 { 20 } + #[allow(dead_code)] fn w(&self) -> i32 { 21 } } trait Baz: Bar { + #[allow(dead_code)] fn c(&self) -> i32 { 30 } diff --git a/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs b/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs index ccf96b9967202..2491bda0917d3 100644 --- a/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs +++ b/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs @@ -9,6 +9,7 @@ trait Foo { } } +#[allow(dead_code)] trait Bar { fn bar(&self) { println!("Bar!"); diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs index 8432012a9ba52..529b9c471d426 100644 --- a/src/tools/miri/tests/pass/dyn-upcast.rs +++ b/src/tools/miri/tests/pass/dyn-upcast.rs @@ -383,14 +383,17 @@ fn struct_() { fn replace_vptr() { trait A { + #[allow(dead_code)] fn foo_a(&self); } trait B { + #[allow(dead_code)] fn foo_b(&self); } trait C: A + B { + #[allow(dead_code)] fn foo_c(&self); } diff --git a/src/tools/miri/tests/pass/weak_memory/weak.rs b/src/tools/miri/tests/pass/weak_memory/weak.rs index 4c3be6b3559ae..e10ccc277f6f1 100644 --- a/src/tools/miri/tests/pass/weak_memory/weak.rs +++ b/src/tools/miri/tests/pass/weak_memory/weak.rs @@ -11,6 +11,7 @@ use std::sync::atomic::Ordering::*; use std::sync::atomic::{fence, AtomicUsize}; use std::thread::spawn; +#[allow(dead_code)] #[derive(Copy, Clone)] struct EvilSend(pub T); diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 094694274269f..e7b1ccf6a0299 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -13,8 +13,9 @@ use std::path::{Path, PathBuf}; // desirable, because large numbers of files are unwieldy in general. See issue // #73494. const ENTRY_LIMIT: usize = 900; -const ISSUES_ENTRY_LIMIT: usize = 1807; -const ROOT_ENTRY_LIMIT: usize = 868; +// FIXME: The following limits should be reduced eventually. +const ISSUES_ENTRY_LIMIT: usize = 1819; +const ROOT_ENTRY_LIMIT: usize = 870; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs index e78226d4083a4..41edab7f8793a 100644 --- a/tests/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs @@ -26,7 +26,9 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn std::ptr::drop_in_place::> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn as Trait>::foo //~ MONO_ITEM fn as Trait>::bar - let _ = &s1 as &Trait; + let r1 = &s1 as &Trait; + r1.foo(); + r1.bar(); let s1 = Struct { _a: 0u64 }; //~ MONO_ITEM fn std::ptr::drop_in_place::> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] diff --git a/tests/codegen-units/item-collection/trait-method-default-impl.rs b/tests/codegen-units/item-collection/trait-method-default-impl.rs index d953582cce9b6..c8a4552b11ac6 100644 --- a/tests/codegen-units/item-collection/trait-method-default-impl.rs +++ b/tests/codegen-units/item-collection/trait-method-default-impl.rs @@ -57,5 +57,8 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn >::bar::<()> 0u32.bar(0i16, ()); + 0i8.foo(); + 0i32.foo(); + 0 } diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs index 34f52ce4e619e..f578b00f27668 100644 --- a/tests/codegen-units/item-collection/unsizing.rs +++ b/tests/codegen-units/item-collection/unsizing.rs @@ -75,5 +75,7 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn ::foo let _wrapper_sized = wrapper_sized as Wrapper; + false.foo(); + 0 } diff --git a/tests/ui-fulldeps/rustc_encodable_hygiene.rs b/tests/ui-fulldeps/rustc_encodable_hygiene.rs index bec7930d4622f..36c684a131e65 100644 --- a/tests/ui-fulldeps/rustc_encodable_hygiene.rs +++ b/tests/ui-fulldeps/rustc_encodable_hygiene.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(rustc_private)] diff --git a/tests/ui/anon-params/anon-params-deprecated.fixed b/tests/ui/anon-params/anon-params-deprecated.fixed index c09e20770846e..8ec1d41a70985 100644 --- a/tests/ui/anon-params/anon-params-deprecated.fixed +++ b/tests/ui/anon-params/anon-params-deprecated.fixed @@ -5,6 +5,7 @@ // edition:2015 // run-rustfix +#[allow(dead_code)] trait T { fn foo(_: i32); //~ WARNING anonymous parameters are deprecated //~| WARNING this is accepted in the current edition diff --git a/tests/ui/anon-params/anon-params-deprecated.rs b/tests/ui/anon-params/anon-params-deprecated.rs index 6f7385da040c5..108ba60a02f58 100644 --- a/tests/ui/anon-params/anon-params-deprecated.rs +++ b/tests/ui/anon-params/anon-params-deprecated.rs @@ -5,6 +5,7 @@ // edition:2015 // run-rustfix +#[allow(dead_code)] trait T { fn foo(i32); //~ WARNING anonymous parameters are deprecated //~| WARNING this is accepted in the current edition diff --git a/tests/ui/anon-params/anon-params-deprecated.stderr b/tests/ui/anon-params/anon-params-deprecated.stderr index 691e2c7951249..541cb004b5b2c 100644 --- a/tests/ui/anon-params/anon-params-deprecated.stderr +++ b/tests/ui/anon-params/anon-params-deprecated.stderr @@ -1,5 +1,5 @@ warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:9:12 + --> $DIR/anon-params-deprecated.rs:10:12 | LL | fn foo(i32); | ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32` @@ -13,7 +13,7 @@ LL | #![warn(anonymous_parameters)] | ^^^^^^^^^^^^^^^^^^^^ warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:12:30 + --> $DIR/anon-params-deprecated.rs:13:30 | LL | fn bar_with_default_impl(String, String) {} | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` @@ -22,7 +22,7 @@ LL | fn bar_with_default_impl(String, String) {} = note: for more information, see issue #41686 warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:12:38 + --> $DIR/anon-params-deprecated.rs:13:38 | LL | fn bar_with_default_impl(String, String) {} | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` diff --git a/tests/ui/associated-consts/associated-const-outer-ty-refs.rs b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs index f32ca0cccfc91..d5e9a2bde0060 100644 --- a/tests/ui/associated-consts/associated-const-outer-ty-refs.rs +++ b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs @@ -1,4 +1,5 @@ -// run-pass +// check-pass + trait Lattice { const BOTTOM: Self; } diff --git a/tests/ui/associated-consts/associated-const-type-parameters.rs b/tests/ui/associated-consts/associated-const-type-parameters.rs index b62d47458be5e..a233b09ff89c6 100644 --- a/tests/ui/associated-consts/associated-const-type-parameters.rs +++ b/tests/ui/associated-consts/associated-const-type-parameters.rs @@ -27,7 +27,7 @@ fn sub() -> i32 { A::X - B::X } -trait Bar: Foo { +trait Bar: Foo { //~ WARN trait `Bar` is never used const Y: i32 = Self::X; } diff --git a/tests/ui/associated-consts/associated-const-type-parameters.stderr b/tests/ui/associated-consts/associated-const-type-parameters.stderr new file mode 100644 index 0000000000000..6ee2a5de1b6ad --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameters.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/associated-const-type-parameters.rs:30:7 + | +LL | trait Bar: Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs index a3f4717791abd..079c44b3a598d 100644 --- a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs +++ b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs @@ -5,7 +5,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy(x: T) { let _x = x; let _x = x; } fn assert_static(_: T) {} diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr b/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr new file mode 100644 index 0000000000000..2e26a434f5d34 --- /dev/null +++ b/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/dyn-impl-trait-type.rs:8:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs index 52199124ea3b5..49e5e72f225e2 100644 --- a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs +++ b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs @@ -7,7 +7,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy(x: T) { let _x = x; let _x = x; } fn assert_static(_: T) {} diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr b/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr new file mode 100644 index 0000000000000..9eddbe462847d --- /dev/null +++ b/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/dyn-rpit-and-let.rs:10:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/rpit.rs b/tests/ui/associated-type-bounds/rpit.rs index 59c7733fbe4ba..557e63b5f71fa 100644 --- a/tests/ui/associated-type-bounds/rpit.rs +++ b/tests/ui/associated-type-bounds/rpit.rs @@ -5,7 +5,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy(x: T) { let _x = x; let _x = x; } fn assert_static(_: T) {} diff --git a/tests/ui/associated-type-bounds/rpit.stderr b/tests/ui/associated-type-bounds/rpit.stderr new file mode 100644 index 0000000000000..76bd75bd2cab3 --- /dev/null +++ b/tests/ui/associated-type-bounds/rpit.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/rpit.rs:8:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed index b9f26a40219b5..128c7dfdda2ed 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait O { type M; } diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs index abff6af73e24b..6b6478419b4c0 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait O { type M; } diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr index 7ca9aff432279..21bc37bb3ea2d 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21 + --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:13:21 | LL | const N: C::M = 4u8; | ^^^ expected associated type, found `u8` diff --git a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs index 93a44c01ce053..60088e443f300 100644 --- a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs +++ b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs @@ -1,5 +1,6 @@ // run-pass +#![allow(dead_code)] #![feature(associated_type_bounds)] #![feature(type_alias_impl_trait)] diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed index 80bbef17469db..adfba994f32dc 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #![allow(unused_variables)] trait Get { diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.rs b/tests/ui/associated-types/associated-types-for-unimpl-trait.rs index 0f6cea8e69fcf..50478171d869a 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.rs +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #![allow(unused_variables)] trait Get { diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr index 17941b6bf1eef..27014fa53d8a2 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:10:40 + --> $DIR/associated-types-for-unimpl-trait.rs:11:40 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` diff --git a/tests/ui/associated-types/associated-types-in-bound-type-arg.rs b/tests/ui/associated-types/associated-types-in-bound-type-arg.rs index 88bb5fe0afeab..05e66a168d9cf 100644 --- a/tests/ui/associated-types/associated-types-in-bound-type-arg.rs +++ b/tests/ui/associated-types/associated-types-in-bound-type-arg.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test the case where we resolve `C::Result` and the trait bound // itself includes a `Self::Item` shorthand. // diff --git a/tests/ui/associated-types/associated-types-issue-20220.rs b/tests/ui/associated-types/associated-types-issue-20220.rs index 19fa7a6085a56..89efce198340f 100644 --- a/tests/ui/associated-types/associated-types-issue-20220.rs +++ b/tests/ui/associated-types/associated-types-issue-20220.rs @@ -4,7 +4,7 @@ use std::vec; -trait IntoIteratorX { +trait IntoIteratorX { //~ WARN trait `IntoIteratorX` is never used type Item; type IntoIter: Iterator; diff --git a/tests/ui/associated-types/associated-types-issue-20220.stderr b/tests/ui/associated-types/associated-types-issue-20220.stderr new file mode 100644 index 0000000000000..c682f46e1409b --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-20220.stderr @@ -0,0 +1,10 @@ +warning: trait `IntoIteratorX` is never used + --> $DIR/associated-types-issue-20220.rs:7:7 + | +LL | trait IntoIteratorX { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-issue-20371.rs b/tests/ui/associated-types/associated-types-issue-20371.rs index ae8a8767d2746..cbec83d45b29d 100644 --- a/tests/ui/associated-types/associated-types-issue-20371.rs +++ b/tests/ui/associated-types/associated-types-issue-20371.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that we are able to have an impl that defines an associated type // before the actual trait. diff --git a/tests/ui/associated-types/associated-types-nested-projections.rs b/tests/ui/associated-types/associated-types-nested-projections.rs index 76ba7496250cc..440f35c8bdef4 100644 --- a/tests/ui/associated-types/associated-types-nested-projections.rs +++ b/tests/ui/associated-types/associated-types-nested-projections.rs @@ -13,7 +13,7 @@ impl<'a> Bound for &'a i32 {} trait IntoIterator { type Iter: Iterator; - fn into_iter(self) -> Self::Iter; + fn into_iter(self) -> Self::Iter; //~ WARN method `into_iter` is never used } impl<'a, T> IntoIterator for &'a [T; 3] { diff --git a/tests/ui/associated-types/associated-types-nested-projections.stderr b/tests/ui/associated-types/associated-types-nested-projections.stderr new file mode 100644 index 0000000000000..97d5a7585736c --- /dev/null +++ b/tests/ui/associated-types/associated-types-nested-projections.stderr @@ -0,0 +1,13 @@ +warning: method `into_iter` is never used + --> $DIR/associated-types-nested-projections.rs:16:8 + | +LL | trait IntoIterator { + | ------------ method in this trait +... +LL | fn into_iter(self) -> Self::Iter; + | ^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs index e09aa3663c6e5..6612598b1b8b4 100644 --- a/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds.rs index dcfae0f37e1da..df0a82ee7ceb0 100644 --- a/tests/ui/associated-types/associated-types-normalize-in-bounds.rs +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. diff --git a/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs b/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs index 107e6b4ce0ca0..e99d0112ec4fd 100644 --- a/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs +++ b/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we correctly handle projection bounds appearing in the // supertrait list (and in conjunction with overloaded operators). In diff --git a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs index a59c327be2101..e172c6e5611d3 100644 --- a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs +++ b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs @@ -6,7 +6,7 @@ trait Int { type T; - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } trait NonZero diff --git a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr new file mode 100644 index 0000000000000..c26ed79a026e4 --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr @@ -0,0 +1,13 @@ +warning: method `dummy` is never used + --> $DIR/associated-types-projection-from-known-type-in-impl.rs:9:8 + | +LL | trait Int + | --- method in this trait +... +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed index 9bc308465ebdd..01f49d52ee212 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed @@ -2,6 +2,7 @@ // Check that we get an error when you use `::Value` in // the trait definition even if there is no default method. +#![allow(dead_code)] trait Get { type Value; } diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs index 549fc8fc618e0..7068a754a12c1 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs @@ -2,6 +2,7 @@ // Check that we get an error when you use `::Value` in // the trait definition even if there is no default method. +#![allow(dead_code)] trait Get { type Value; } diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 64a88525af8d4..79200dc3acc24 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:11:40 | LL | fn okay(&self, foo: U, bar: ::Value); | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs index 3b8c8c019e50b..a2d6c9ff5a45b 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Check that we do not get an error when you use `::Value` in // the trait definition if there is no default method and for every impl, // `Self` does implement `Get`. diff --git a/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs b/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs index 3c830d37060ab..1768fd1687b4e 100644 --- a/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs +++ b/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/associated-types/associated-types-resolve-lifetime.rs b/tests/ui/associated-types/associated-types-resolve-lifetime.rs index 52f2324d72ab7..563d0c1182211 100644 --- a/tests/ui/associated-types/associated-types-resolve-lifetime.rs +++ b/tests/ui/associated-types/associated-types-resolve-lifetime.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Get { diff --git a/tests/ui/associated-types/impl-wf-cycle-5.fixed b/tests/ui/associated-types/impl-wf-cycle-5.fixed index bff6ca90975d2..2b8f1e0d865ee 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.fixed +++ b/tests/ui/associated-types/impl-wf-cycle-5.fixed @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-5.rs b/tests/ui/associated-types/impl-wf-cycle-5.rs index a822e1fb0081b..e6de292ca5c91 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.rs +++ b/tests/ui/associated-types/impl-wf-cycle-5.rs @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-5.stderr b/tests/ui/associated-types/impl-wf-cycle-5.stderr index 284a50bb9a3be..61edf18b43d97 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-5.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-5.rs:20:1 + --> $DIR/impl-wf-cycle-5.rs:22:1 | LL | / impl Grault for (T,) LL | | @@ -12,7 +12,7 @@ LL | type A = (); | ------ associated type `<(T,) as Grault>::A` is specified here | note: required for `(T,)` to implement `Grault` - --> $DIR/impl-wf-cycle-5.rs:20:9 + --> $DIR/impl-wf-cycle-5.rs:22:9 | LL | impl Grault for (T,) | ^^^^^^ ^^^^ diff --git a/tests/ui/associated-types/impl-wf-cycle-6.fixed b/tests/ui/associated-types/impl-wf-cycle-6.fixed index 73ed64f7ce381..5ddf1faefe088 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.fixed +++ b/tests/ui/associated-types/impl-wf-cycle-6.fixed @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-6.rs b/tests/ui/associated-types/impl-wf-cycle-6.rs index 20d635cac5d6f..28f6deb77ce1f 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.rs +++ b/tests/ui/associated-types/impl-wf-cycle-6.rs @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-6.stderr b/tests/ui/associated-types/impl-wf-cycle-6.stderr index c9b5d8060be68..1c7495033183f 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-6.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-6.rs:20:1 + --> $DIR/impl-wf-cycle-6.rs:22:1 | LL | / impl Grault for (T,) LL | | @@ -11,7 +11,7 @@ LL | type A = (); | ------ associated type `<(T,) as Grault>::A` is specified here | note: required for `(T,)` to implement `Grault` - --> $DIR/impl-wf-cycle-6.rs:20:17 + --> $DIR/impl-wf-cycle-6.rs:22:17 | LL | impl Grault for (T,) | ^^^^^^ ^^^^ diff --git a/tests/ui/auto-traits/auto-trait-validation.fixed b/tests/ui/auto-traits/auto-trait-validation.fixed index da878ac6222bb..e37fed9faabae 100644 --- a/tests/ui/auto-traits/auto-trait-validation.fixed +++ b/tests/ui/auto-traits/auto-trait-validation.fixed @@ -1,4 +1,5 @@ #![feature(auto_traits)] +#![allow(dead_code)] // run-rustfix diff --git a/tests/ui/auto-traits/auto-trait-validation.rs b/tests/ui/auto-traits/auto-trait-validation.rs index d43055e270bd5..e209aa1322081 100644 --- a/tests/ui/auto-traits/auto-trait-validation.rs +++ b/tests/ui/auto-traits/auto-trait-validation.rs @@ -1,4 +1,5 @@ #![feature(auto_traits)] +#![allow(dead_code)] // run-rustfix diff --git a/tests/ui/auto-traits/auto-trait-validation.stderr b/tests/ui/auto-traits/auto-trait-validation.stderr index 89b63d23d4c8e..a6e5ac54869d2 100644 --- a/tests/ui/auto-traits/auto-trait-validation.stderr +++ b/tests/ui/auto-traits/auto-trait-validation.stderr @@ -1,5 +1,5 @@ error[E0567]: auto traits cannot have generic parameters - --> $DIR/auto-trait-validation.rs:5:19 + --> $DIR/auto-trait-validation.rs:6:19 | LL | auto trait Generic {} | -------^^^ help: remove the parameters @@ -7,7 +7,7 @@ LL | auto trait Generic {} | auto trait cannot have generic parameters error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/auto-trait-validation.rs:7:17 + --> $DIR/auto-trait-validation.rs:8:17 | LL | auto trait Bound : Copy {} | -----^^^^^^^ help: remove the super traits or lifetime bounds @@ -15,7 +15,7 @@ LL | auto trait Bound : Copy {} | auto traits cannot have super traits or lifetime bounds error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/auto-trait-validation.rs:9:25 + --> $DIR/auto-trait-validation.rs:10:25 | LL | auto trait LifetimeBound : 'static {} | -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds @@ -23,7 +23,7 @@ LL | auto trait LifetimeBound : 'static {} | auto traits cannot have super traits or lifetime bounds error[E0380]: auto traits cannot have associated items - --> $DIR/auto-trait-validation.rs:11:25 + --> $DIR/auto-trait-validation.rs:12:25 | LL | auto trait MyTrait { fn foo() {} } | ------- ---^^^----- diff --git a/tests/ui/auto-traits/auto-traits.rs b/tests/ui/auto-traits/auto-traits.rs index 6d8e1a52ec129..1e0fbcc1fdf63 100644 --- a/tests/ui/auto-traits/auto-traits.rs +++ b/tests/ui/auto-traits/auto-traits.rs @@ -19,8 +19,8 @@ fn take_auto_unsafe(_: T) {} fn main() { // Parse inside functions. - auto trait AutoInner {} - unsafe auto trait AutoUnsafeInner {} + auto trait AutoInner {} //~ WARN trait `AutoInner` is never used + unsafe auto trait AutoUnsafeInner {} //~ WARN trait `AutoUnsafeInner` is never used take_auto(0); take_auto(AutoBool(true)); diff --git a/tests/ui/auto-traits/auto-traits.stderr b/tests/ui/auto-traits/auto-traits.stderr new file mode 100644 index 0000000000000..34be8d3f67b8d --- /dev/null +++ b/tests/ui/auto-traits/auto-traits.stderr @@ -0,0 +1,16 @@ +warning: trait `AutoInner` is never used + --> $DIR/auto-traits.rs:22:16 + | +LL | auto trait AutoInner {} + | ^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: trait `AutoUnsafeInner` is never used + --> $DIR/auto-traits.rs:23:23 + | +LL | unsafe auto trait AutoUnsafeInner {} + | ^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs index 2edc52c6f55f0..7e8820cb2c65d 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_imports)] diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs b/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs index 8d24771578444..50914b1de53f2 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Simple test case of implementing a trait with super-builtin-kinds. // pretty-expanded FIXME #23616 diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs b/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs index f999dfff786eb..0577acc572ad5 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Tests correct implementation of traits with super-builtin-kinds // using a bounded type parameter. diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs index 249481467e646..be6a6bb8b1755 100644 --- a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs +++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs @@ -8,7 +8,7 @@ trait Foo { fn foo(&self, _: T) -> u32 { 42 } } -trait Bar { +trait Bar { //~ WARN trait `Bar` is never used fn bar(&self) { println!("Bar!"); } } diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr new file mode 100644 index 0000000000000..952687e98d0ef --- /dev/null +++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/cast-rfc0401-vtable-kinds.rs:11:7 + | +LL | trait Bar { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/cast/fat-ptr-cast-rpass.rs b/tests/ui/cast/fat-ptr-cast-rpass.rs index f5747eb8b9666..c79468cadddd9 100644 --- a/tests/ui/cast/fat-ptr-cast-rpass.rs +++ b/tests/ui/cast/fat-ptr-cast-rpass.rs @@ -3,7 +3,7 @@ #![feature(ptr_metadata)] trait Foo { - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } struct Bar; diff --git a/tests/ui/cast/fat-ptr-cast-rpass.stderr b/tests/ui/cast/fat-ptr-cast-rpass.stderr new file mode 100644 index 0000000000000..d01688e0cc3b0 --- /dev/null +++ b/tests/ui/cast/fat-ptr-cast-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/fat-ptr-cast-rpass.rs:6:8 + | +LL | trait Foo { + | --- method in this trait +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/coercion/issue-14589.rs b/tests/ui/coercion/issue-14589.rs index f92385f8d7275..6f95b30be06ae 100644 --- a/tests/ui/coercion/issue-14589.rs +++ b/tests/ui/coercion/issue-14589.rs @@ -19,6 +19,6 @@ impl Test { fn send(&self, _: T) {} } -trait Foo { fn dummy(&self) { }} +trait Foo { fn dummy(&self) { }} //~ WARN method `dummy` is never used struct Output(#[allow(dead_code)] isize); impl Foo for Output {} diff --git a/tests/ui/coercion/issue-14589.stderr b/tests/ui/coercion/issue-14589.stderr new file mode 100644 index 0000000000000..37b7fce7462b3 --- /dev/null +++ b/tests/ui/coercion/issue-14589.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-14589.rs:22:16 + | +LL | trait Foo { fn dummy(&self) { }} + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/coherence/coherence-multidispatch-tuple.rs b/tests/ui/coherence/coherence-multidispatch-tuple.rs index fa1d4bbb49665..b04b2a296b5b4 100644 --- a/tests/ui/coherence/coherence-multidispatch-tuple.rs +++ b/tests/ui/coherence/coherence-multidispatch-tuple.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_imports)] // pretty-expanded FIXME #23616 diff --git a/tests/ui/const-generics/associated-type-bound.rs b/tests/ui/const-generics/associated-type-bound.rs index 3044736b47e05..0a57352c10da1 100644 --- a/tests/ui/const-generics/associated-type-bound.rs +++ b/tests/ui/const-generics/associated-type-bound.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass trait Bar {} trait Foo { diff --git a/tests/ui/const-generics/condition-in-trait-const-arg.rs b/tests/ui/const-generics/condition-in-trait-const-arg.rs index 6f85237cf0aaf..74a663a53ec6b 100644 --- a/tests/ui/const-generics/condition-in-trait-const-arg.rs +++ b/tests/ui/const-generics/condition-in-trait-const-arg.rs @@ -1,5 +1,5 @@ // Checks that `impl Trait<{anon_const}> for Type` evaluates successfully. -// run-pass +// check-pass // revisions: full min #![cfg_attr(full, feature(generic_const_exprs))] diff --git a/tests/ui/const-generics/dyn-supertraits.rs b/tests/ui/const-generics/dyn-supertraits.rs index 3dee326a186e9..bb4924529824b 100644 --- a/tests/ui/const-generics/dyn-supertraits.rs +++ b/tests/ui/const-generics/dyn-supertraits.rs @@ -4,7 +4,7 @@ trait Foo { fn myfun(&self) -> usize; } trait Bar : Foo {} -trait Baz: Foo<3> {} +trait Baz: Foo<3> {} //~ WARN trait `Baz` is never used struct FooType; struct BarType; @@ -23,10 +23,10 @@ impl Foo<3> for BazType { impl Baz for BazType {} trait Foz {} -trait Boz: Foo<3> + Foz {} +trait Boz: Foo<3> + Foz {} //~ WARN trait `Boz` is never used trait Bok: Foo + Foz {} -struct FozType; +struct FozType; //~ WARN struct `FozType` is never constructed struct BozType; struct BokType; diff --git a/tests/ui/const-generics/dyn-supertraits.stderr b/tests/ui/const-generics/dyn-supertraits.stderr new file mode 100644 index 0000000000000..38b67ef4403a1 --- /dev/null +++ b/tests/ui/const-generics/dyn-supertraits.stderr @@ -0,0 +1,22 @@ +warning: trait `Baz` is never used + --> $DIR/dyn-supertraits.rs:7:7 + | +LL | trait Baz: Foo<3> {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: trait `Boz` is never used + --> $DIR/dyn-supertraits.rs:26:7 + | +LL | trait Boz: Foo<3> + Foz {} + | ^^^ + +warning: struct `FozType` is never constructed + --> $DIR/dyn-supertraits.rs:29:8 + | +LL | struct FozType; + | ^^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/const-generics/issues/issue-69654-run-pass.rs b/tests/ui/const-generics/issues/issue-69654-run-pass.rs index 63d7fde78ac8a..21d6270b1fafa 100644 --- a/tests/ui/const-generics/issues/issue-69654-run-pass.rs +++ b/tests/ui/const-generics/issues/issue-69654-run-pass.rs @@ -1,5 +1,5 @@ // run-pass -trait Bar {} +trait Bar {} //~ WARN trait `Bar` is never used impl Bar for [u8; 7] {} struct Foo {} diff --git a/tests/ui/const-generics/issues/issue-69654-run-pass.stderr b/tests/ui/const-generics/issues/issue-69654-run-pass.stderr new file mode 100644 index 0000000000000..7b3cd4f375fd0 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-69654-run-pass.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/issue-69654-run-pass.rs:2:7 + | +LL | trait Bar {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/const-block-item.rs b/tests/ui/consts/const-block-item.rs index cf0d4441d4a9b..a04f4db263bb2 100644 --- a/tests/ui/consts/const-block-item.rs +++ b/tests/ui/consts/const-block-item.rs @@ -2,7 +2,7 @@ #![allow(unused_imports)] mod foo { - pub trait Value { + pub trait Value { //~ WARN trait `Value` is never used fn value(&self) -> usize; } } diff --git a/tests/ui/consts/const-block-item.stderr b/tests/ui/consts/const-block-item.stderr new file mode 100644 index 0000000000000..04658742b56ce --- /dev/null +++ b/tests/ui/consts/const-block-item.stderr @@ -0,0 +1,10 @@ +warning: trait `Value` is never used + --> $DIR/const-block-item.rs:5:15 + | +LL | pub trait Value { + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/underscore_const_names.rs b/tests/ui/consts/underscore_const_names.rs index d0e625bf1997a..e2ae5a9d53aac 100644 --- a/tests/ui/consts/underscore_const_names.rs +++ b/tests/ui/consts/underscore_const_names.rs @@ -2,12 +2,12 @@ #![deny(unused)] -trait Trt {} +pub trait Trt {} pub struct Str {} impl Trt for Str {} macro_rules! check_impl { - ($struct:ident,$trait:ident) => { + ($struct:ident, $trait:ident) => { const _ : () = { use std::marker::PhantomData; struct ImplementsTrait(PhantomData); diff --git a/tests/ui/default-method-parsing.rs b/tests/ui/default-method-parsing.rs index 9ffb8d94a59b3..5001d58f0a48e 100644 --- a/tests/ui/default-method-parsing.rs +++ b/tests/ui/default-method-parsing.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/delegation/target-expr-pass.rs b/tests/ui/delegation/target-expr-pass.rs index 56068dfce01d7..4ccb81c292aa5 100644 --- a/tests/ui/delegation/target-expr-pass.rs +++ b/tests/ui/delegation/target-expr-pass.rs @@ -14,14 +14,14 @@ reuse to_reuse::foo {{ x + self }} -trait Trait { +trait Trait { //~ WARN trait `Trait` is never used fn bar(&self, x: i32) -> i32 { x } } -struct F; +struct F; //~ WARN struct `F` is never constructed impl Trait for F {} -struct S(F); +struct S(F); //~ WARN struct `S` is never constructed impl Trait for S { reuse ::bar { #[allow(unused_imports)] diff --git a/tests/ui/delegation/target-expr-pass.stderr b/tests/ui/delegation/target-expr-pass.stderr index ea594f8a26a5b..dd1f3a14e0bd8 100644 --- a/tests/ui/delegation/target-expr-pass.stderr +++ b/tests/ui/delegation/target-expr-pass.stderr @@ -7,5 +7,25 @@ LL | #![feature(fn_delegation)] = note: see issue #118212 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +warning: trait `Trait` is never used + --> $DIR/target-expr-pass.rs:17:7 + | +LL | trait Trait { + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: struct `F` is never constructed + --> $DIR/target-expr-pass.rs:21:8 + | +LL | struct F; + | ^ + +warning: struct `S` is never constructed + --> $DIR/target-expr-pass.rs:24:8 + | +LL | struct S(F); + | ^ + +warning: 4 warnings emitted diff --git a/tests/ui/deriving/deriving-bounds.rs b/tests/ui/deriving/deriving-bounds.rs index f0b921d0e7c0e..f3e7cf99437d5 100644 --- a/tests/ui/deriving/deriving-bounds.rs +++ b/tests/ui/deriving/deriving-bounds.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #[derive(Copy, Clone)] struct Test; diff --git a/tests/ui/drop/drop-struct-as-object.rs b/tests/ui/drop/drop-struct-as-object.rs index 377027a4fc5f2..1aa6877704253 100644 --- a/tests/ui/drop/drop-struct-as-object.rs +++ b/tests/ui/drop/drop-struct-as-object.rs @@ -12,7 +12,7 @@ struct Cat { } trait Dummy { - fn get(&self) -> usize; + fn get(&self) -> usize; //~ WARN method `get` is never used } impl Dummy for Cat { diff --git a/tests/ui/drop/drop-struct-as-object.stderr b/tests/ui/drop/drop-struct-as-object.stderr new file mode 100644 index 0000000000000..10527c968ed70 --- /dev/null +++ b/tests/ui/drop/drop-struct-as-object.stderr @@ -0,0 +1,12 @@ +warning: method `get` is never used + --> $DIR/drop-struct-as-object.rs:15:8 + | +LL | trait Dummy { + | ----- method in this trait +LL | fn get(&self) -> usize; + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/dynamically-sized-types/dst-coercions.rs b/tests/ui/dynamically-sized-types/dst-coercions.rs index 66688e93fb80d..1efdf1de0e61c 100644 --- a/tests/ui/dynamically-sized-types/dst-coercions.rs +++ b/tests/ui/dynamically-sized-types/dst-coercions.rs @@ -5,7 +5,7 @@ // pretty-expanded FIXME #23616 struct S; -trait T { fn dummy(&self) { } } +trait T { fn dummy(&self) { } } //~ WARN method `dummy` is never used impl T for S {} pub fn main() { diff --git a/tests/ui/dynamically-sized-types/dst-coercions.stderr b/tests/ui/dynamically-sized-types/dst-coercions.stderr new file mode 100644 index 0000000000000..e4721ce50a045 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-coercions.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/dst-coercions.rs:8:14 + | +LL | trait T { fn dummy(&self) { } } + | - ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/empty-type-parameter-list.rs b/tests/ui/empty-type-parameter-list.rs index e168cd03b2746..23d09fbf281d0 100644 --- a/tests/ui/empty-type-parameter-list.rs +++ b/tests/ui/empty-type-parameter-list.rs @@ -3,7 +3,7 @@ // no type parameters at all struct S<>; -trait T<> {} +trait T<> {} //~ WARN trait `T` is never used enum E<> { V } impl<> T<> for S<> {} impl T for E {} diff --git a/tests/ui/empty-type-parameter-list.stderr b/tests/ui/empty-type-parameter-list.stderr new file mode 100644 index 0000000000000..31a5015e99349 --- /dev/null +++ b/tests/ui/empty-type-parameter-list.stderr @@ -0,0 +1,10 @@ +warning: trait `T` is never used + --> $DIR/empty-type-parameter-list.rs:6:7 + | +LL | trait T<> {} + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed index bb093a4af4a3e..3c71587c8e399 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![allow(dropping_references)] struct Foo { diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs index 1a9f89c054f39..075d4cbe02b31 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![allow(dropping_references)] struct Foo { diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr index d2d69ce6daf72..13b6ee9987e88 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr @@ -1,5 +1,5 @@ error[E0040]: explicit use of destructor method - --> $DIR/explicit-call-to-supertrait-dtor.rs:22:14 + --> $DIR/explicit-call-to-supertrait-dtor.rs:23:14 | LL | self.drop(); | ^^^^ explicit destructor calls not allowed diff --git a/tests/ui/extern/no-mangle-associated-fn.rs b/tests/ui/extern/no-mangle-associated-fn.rs index ecd44abbf264c..56afd8b90926e 100644 --- a/tests/ui/extern/no-mangle-associated-fn.rs +++ b/tests/ui/extern/no-mangle-associated-fn.rs @@ -12,7 +12,7 @@ impl Foo { } } -trait Bar { +trait Bar { //~ WARN trait `Bar` is never used fn qux() -> u8; } diff --git a/tests/ui/extern/no-mangle-associated-fn.stderr b/tests/ui/extern/no-mangle-associated-fn.stderr new file mode 100644 index 0000000000000..772cbf6cf7dd7 --- /dev/null +++ b/tests/ui/extern/no-mangle-associated-fn.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/no-mangle-associated-fn.rs:15:7 + | +LL | trait Bar { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generic-associated-types/issue-88360.fixed b/tests/ui/generic-associated-types/issue-88360.fixed index 3dea8bf7ac81d..6fb1e2559c0ac 100644 --- a/tests/ui/generic-associated-types/issue-88360.fixed +++ b/tests/ui/generic-associated-types/issue-88360.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait GatTrait { type Gat<'a> where Self: 'a; diff --git a/tests/ui/generic-associated-types/issue-88360.rs b/tests/ui/generic-associated-types/issue-88360.rs index 4d4c7ea318078..c8f07955b6129 100644 --- a/tests/ui/generic-associated-types/issue-88360.rs +++ b/tests/ui/generic-associated-types/issue-88360.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait GatTrait { type Gat<'a> where Self: 'a; diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr index 49d36acadd657..488e50d2843bf 100644 --- a/tests/ui/generic-associated-types/issue-88360.stderr +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-88360.rs:15:9 + --> $DIR/issue-88360.rs:16:9 | LL | trait SuperTrait | - found this type parameter diff --git a/tests/ui/generics/generic-no-mangle.fixed b/tests/ui/generics/generic-no-mangle.fixed index aa6d6310f5fe3..f51040358c0b3 100644 --- a/tests/ui/generics/generic-no-mangle.fixed +++ b/tests/ui/generics/generic-no-mangle.fixed @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(dead_code)] #![deny(no_mangle_generic_items)] diff --git a/tests/ui/generics/generic-no-mangle.rs b/tests/ui/generics/generic-no-mangle.rs index 8a59ca75aafd2..02015331c5712 100644 --- a/tests/ui/generics/generic-no-mangle.rs +++ b/tests/ui/generics/generic-no-mangle.rs @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(dead_code)] #![deny(no_mangle_generic_items)] #[no_mangle] diff --git a/tests/ui/impl-trait/example-st.rs b/tests/ui/impl-trait/example-st.rs index 4e1aa3a085921..1e6ebc52365dc 100644 --- a/tests/ui/impl-trait/example-st.rs +++ b/tests/ui/impl-trait/example-st.rs @@ -3,7 +3,7 @@ struct State; type Error = (); -trait Bind { +trait Bind { //~ WARN trait `Bind` is never used type Output; fn bind(self, f: F) -> Self::Output; } diff --git a/tests/ui/impl-trait/example-st.stderr b/tests/ui/impl-trait/example-st.stderr new file mode 100644 index 0000000000000..f722d7f658215 --- /dev/null +++ b/tests/ui/impl-trait/example-st.stderr @@ -0,0 +1,10 @@ +warning: trait `Bind` is never used + --> $DIR/example-st.rs:6:7 + | +LL | trait Bind { + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed index 8dc8e045d4738..ecc8488a15299 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed @@ -1,6 +1,7 @@ // edition:2021 // run-rustfix +#![allow(dead_code)] trait Trait { #[allow(async_fn_in_trait)] async fn foo(); diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs index 30b04d87b9a3e..860fea07df964 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs @@ -1,6 +1,7 @@ // edition:2021 // run-rustfix +#![allow(dead_code)] trait Trait { #[allow(async_fn_in_trait)] async fn foo(); diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr index cf68ed87030a9..45fd79badb30f 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`, `baz` - --> $DIR/suggest-missing-item.rs:19:1 + --> $DIR/suggest-missing-item.rs:20:1 | LL | async fn foo(); | --------------- `foo` from trait diff --git a/tests/ui/impl-trait/type-alias-generic-param.rs b/tests/ui/impl-trait/type-alias-generic-param.rs index 1211625dac9cc..e4b2e4124202f 100644 --- a/tests/ui/impl-trait/type-alias-generic-param.rs +++ b/tests/ui/impl-trait/type-alias-generic-param.rs @@ -5,7 +5,7 @@ // run-pass #![feature(impl_trait_in_assoc_type)] -trait Meow { +trait Meow { //~ WARN trait `Meow` is never used type MeowType; fn meow(self) -> Self::MeowType; } diff --git a/tests/ui/impl-trait/type-alias-generic-param.stderr b/tests/ui/impl-trait/type-alias-generic-param.stderr new file mode 100644 index 0000000000000..e4115dc1319d1 --- /dev/null +++ b/tests/ui/impl-trait/type-alias-generic-param.stderr @@ -0,0 +1,10 @@ +warning: trait `Meow` is never used + --> $DIR/type-alias-generic-param.rs:8:7 + | +LL | trait Meow { + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-14399.rs b/tests/ui/issues/issue-14399.rs index 7b32bf8e4cbb7..0c6c4d8dc6bd3 100644 --- a/tests/ui/issues/issue-14399.rs +++ b/tests/ui/issues/issue-14399.rs @@ -9,7 +9,7 @@ #[derive(Clone)] struct B1; -trait A { fn foo(&self) {} } +trait A { fn foo(&self) {} } //~ WARN method `foo` is never used impl A for B1 {} fn main() { diff --git a/tests/ui/issues/issue-14399.stderr b/tests/ui/issues/issue-14399.stderr new file mode 100644 index 0000000000000..d226ece6fb0b6 --- /dev/null +++ b/tests/ui/issues/issue-14399.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/issue-14399.rs:12:14 + | +LL | trait A { fn foo(&self) {} } + | - ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-15858.rs b/tests/ui/issues/issue-15858.rs index 77941c07671d6..e3e3c293d7a74 100644 --- a/tests/ui/issues/issue-15858.rs +++ b/tests/ui/issues/issue-15858.rs @@ -2,7 +2,7 @@ static mut DROP_RAN: bool = false; trait Bar { - fn do_something(&mut self); + fn do_something(&mut self); //~ WARN method `do_something` is never used } struct BarImpl; diff --git a/tests/ui/issues/issue-15858.stderr b/tests/ui/issues/issue-15858.stderr new file mode 100644 index 0000000000000..f36bcc21bd7fb --- /dev/null +++ b/tests/ui/issues/issue-15858.stderr @@ -0,0 +1,12 @@ +warning: method `do_something` is never used + --> $DIR/issue-15858.rs:5:8 + | +LL | trait Bar { + | --- method in this trait +LL | fn do_something(&mut self); + | ^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-17351.rs b/tests/ui/issues/issue-17351.rs index 62f6bcf15e3e7..12bb8a73b7bd4 100644 --- a/tests/ui/issues/issue-17351.rs +++ b/tests/ui/issues/issue-17351.rs @@ -1,7 +1,7 @@ // run-pass // pretty-expanded FIXME #23616 -trait Str { fn foo(&self) {} } +trait Str { fn foo(&self) {} } //~ WARN method `foo` is never used impl Str for str {} impl<'a, S: ?Sized> Str for &'a S where S: Str {} diff --git a/tests/ui/issues/issue-17351.stderr b/tests/ui/issues/issue-17351.stderr new file mode 100644 index 0000000000000..3242d578dabce --- /dev/null +++ b/tests/ui/issues/issue-17351.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/issue-17351.rs:4:16 + | +LL | trait Str { fn foo(&self) {} } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-18173.rs b/tests/ui/issues/issue-18173.rs index 11468040ee530..010efee9f8ab6 100644 --- a/tests/ui/issues/issue-18173.rs +++ b/tests/ui/issues/issue-18173.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass trait Foo { type T; } diff --git a/tests/ui/issues/issue-20055-box-trait.rs b/tests/ui/issues/issue-20055-box-trait.rs index 772cd9d7eda82..36f597450adb8 100644 --- a/tests/ui/issues/issue-20055-box-trait.rs +++ b/tests/ui/issues/issue-20055-box-trait.rs @@ -8,7 +8,7 @@ // statement surrounding the `match`. trait Boo { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } impl Boo for [i8; 1] { } diff --git a/tests/ui/issues/issue-20055-box-trait.stderr b/tests/ui/issues/issue-20055-box-trait.stderr new file mode 100644 index 0000000000000..db9d359e2252c --- /dev/null +++ b/tests/ui/issues/issue-20055-box-trait.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-20055-box-trait.rs:11:8 + | +LL | trait Boo { + | --- method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-21909.rs b/tests/ui/issues/issue-21909.rs index 7cb558d9a4fa6..6a6cdcfee159d 100644 --- a/tests/ui/issues/issue-21909.rs +++ b/tests/ui/issues/issue-21909.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait A { diff --git a/tests/ui/issues/issue-23485.rs b/tests/ui/issues/issue-23485.rs index 1dd3d9293bcc6..07ed0f1b00df8 100644 --- a/tests/ui/issues/issue-23485.rs +++ b/tests/ui/issues/issue-23485.rs @@ -17,7 +17,7 @@ trait Iterator { fn next(&mut self) -> Option; - fn clone_first(mut self) -> Option<::Target> where + fn clone_first(mut self) -> Option<::Target> where //~ WARN method `clone_first` is never used Self: Sized, Self::Item: Deref, ::Target: Clone, diff --git a/tests/ui/issues/issue-23485.stderr b/tests/ui/issues/issue-23485.stderr new file mode 100644 index 0000000000000..ed2d2400d0d93 --- /dev/null +++ b/tests/ui/issues/issue-23485.stderr @@ -0,0 +1,13 @@ +warning: method `clone_first` is never used + --> $DIR/issue-23485.rs:20:8 + | +LL | trait Iterator { + | -------- method in this trait +... +LL | fn clone_first(mut self) -> Option<::Target> where + | ^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-2989.rs b/tests/ui/issues/issue-2989.rs index c0b67374370e7..a95867514073c 100644 --- a/tests/ui/issues/issue-2989.rs +++ b/tests/ui/issues/issue-2989.rs @@ -1,8 +1,8 @@ // run-pass #![allow(non_camel_case_types)] -trait methods { - fn to_bytes(&self) -> Vec ; +trait methods { //~ WARN trait `methods` is never used + fn to_bytes(&self) -> Vec; } impl methods for () { diff --git a/tests/ui/issues/issue-2989.stderr b/tests/ui/issues/issue-2989.stderr new file mode 100644 index 0000000000000..57181607cecd3 --- /dev/null +++ b/tests/ui/issues/issue-2989.stderr @@ -0,0 +1,10 @@ +warning: trait `methods` is never used + --> $DIR/issue-2989.rs:4:7 + | +LL | trait methods { + | ^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-34074.rs b/tests/ui/issues/issue-34074.rs index 0600d3937c16e..ca7d7b49a042f 100644 --- a/tests/ui/issues/issue-34074.rs +++ b/tests/ui/issues/issue-34074.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Make sure several unnamed function parameters don't conflict with each other trait Tr { diff --git a/tests/ui/issues/issue-34503.rs b/tests/ui/issues/issue-34503.rs index 26e7358408f48..d2c95d990ecde 100644 --- a/tests/ui/issues/issue-34503.rs +++ b/tests/ui/issues/issue-34503.rs @@ -2,7 +2,7 @@ fn main() { struct X; trait Foo { - fn foo(&self) where (T, Option): Ord {} + fn foo(&self) where (T, Option): Ord {} //~ WARN methods `foo` and `bar` are never used fn bar(&self, x: &Option) -> bool where Option: Ord { *x < *x } } diff --git a/tests/ui/issues/issue-34503.stderr b/tests/ui/issues/issue-34503.stderr new file mode 100644 index 0000000000000..60d8d76a61965 --- /dev/null +++ b/tests/ui/issues/issue-34503.stderr @@ -0,0 +1,14 @@ +warning: methods `foo` and `bar` are never used + --> $DIR/issue-34503.rs:5:12 + | +LL | trait Foo { + | --- methods in this trait +LL | fn foo(&self) where (T, Option): Ord {} + | ^^^ +LL | fn bar(&self, x: &Option) -> bool + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-3563-3.rs b/tests/ui/issues/issue-3563-3.rs index bedfdab97d58b..6346b82167cb8 100644 --- a/tests/ui/issues/issue-3563-3.rs +++ b/tests/ui/issues/issue-3563-3.rs @@ -112,7 +112,7 @@ trait Canvas { // Unlike interfaces traits support default implementations. // Got an ICE as soon as I added this method. - fn add_points(&mut self, shapes: &[Point]) { + fn add_points(&mut self, shapes: &[Point]) { //~ WARN method `add_points` is never used for pt in shapes {self.add_point(*pt)}; } } diff --git a/tests/ui/issues/issue-3563-3.stderr b/tests/ui/issues/issue-3563-3.stderr new file mode 100644 index 0000000000000..bd65c1e3fd5b4 --- /dev/null +++ b/tests/ui/issues/issue-3563-3.stderr @@ -0,0 +1,13 @@ +warning: method `add_points` is never used + --> $DIR/issue-3563-3.rs:115:8 + | +LL | trait Canvas { + | ------ method in this trait +... +LL | fn add_points(&mut self, shapes: &[Point]) { + | ^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-50571.fixed b/tests/ui/issues/issue-50571.fixed index 2f8c925b85328..13c830cd0d4b1 100644 --- a/tests/ui/issues/issue-50571.fixed +++ b/tests/ui/issues/issue-50571.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn foo(_: [i32; 2]) {} //~^ ERROR: patterns aren't allowed in methods without bodies diff --git a/tests/ui/issues/issue-50571.rs b/tests/ui/issues/issue-50571.rs index 56f422e7d5838..6fe13e3f707db 100644 --- a/tests/ui/issues/issue-50571.rs +++ b/tests/ui/issues/issue-50571.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn foo([a, b]: [i32; 2]) {} //~^ ERROR: patterns aren't allowed in methods without bodies diff --git a/tests/ui/issues/issue-50571.stderr b/tests/ui/issues/issue-50571.stderr index fe47790f1ddfb..12256ded1c0a8 100644 --- a/tests/ui/issues/issue-50571.stderr +++ b/tests/ui/issues/issue-50571.stderr @@ -1,5 +1,5 @@ error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/issue-50571.rs:4:12 + --> $DIR/issue-50571.rs:5:12 | LL | fn foo([a, b]: [i32; 2]) {} | ^^^^^^ diff --git a/tests/ui/issues/issue-7575.rs b/tests/ui/issues/issue-7575.rs index ac69f2b1c80b6..0074f660c4ef0 100644 --- a/tests/ui/issues/issue-7575.rs +++ b/tests/ui/issues/issue-7575.rs @@ -1,6 +1,6 @@ // run-pass -trait Foo { +trait Foo { //~ WARN trait `Foo` is never used fn new() -> bool { false } fn dummy(&self) { } } diff --git a/tests/ui/issues/issue-7575.stderr b/tests/ui/issues/issue-7575.stderr new file mode 100644 index 0000000000000..2f987d19c80ce --- /dev/null +++ b/tests/ui/issues/issue-7575.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/issue-7575.rs:3:7 + | +LL | trait Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-7911.rs b/tests/ui/issues/issue-7911.rs index d4db3b0776bca..114574b9009d8 100644 --- a/tests/ui/issues/issue-7911.rs +++ b/tests/ui/issues/issue-7911.rs @@ -4,7 +4,7 @@ #![allow(unused_variables)] // unused foobar_immut + foobar_mut trait FooBar { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } struct Bar(#[allow(dead_code)] i32); struct Foo { bar: Bar } diff --git a/tests/ui/issues/issue-7911.stderr b/tests/ui/issues/issue-7911.stderr new file mode 100644 index 0000000000000..ead7ee191ac9b --- /dev/null +++ b/tests/ui/issues/issue-7911.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-7911.rs:7:8 + | +LL | trait FooBar { + | ------ method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-8248.rs b/tests/ui/issues/issue-8248.rs index 31a305c31bee2..94b1a5203b47e 100644 --- a/tests/ui/issues/issue-8248.rs +++ b/tests/ui/issues/issue-8248.rs @@ -2,7 +2,7 @@ // pretty-expanded FIXME #23616 trait A { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } struct B; impl A for B {} diff --git a/tests/ui/issues/issue-8248.stderr b/tests/ui/issues/issue-8248.stderr new file mode 100644 index 0000000000000..a0098bcb771ae --- /dev/null +++ b/tests/ui/issues/issue-8248.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-8248.rs:5:8 + | +LL | trait A { + | - method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-9951.rs b/tests/ui/issues/issue-9951.rs index 2698a3b17c6c2..5db3f74efaa3e 100644 --- a/tests/ui/issues/issue-9951.rs +++ b/tests/ui/issues/issue-9951.rs @@ -4,7 +4,7 @@ #![allow(unused_variables)] trait Bar { - fn noop(&self); + fn noop(&self); //~ WARN method `noop` is never used } impl Bar for u8 { fn noop(&self) {} diff --git a/tests/ui/issues/issue-9951.stderr b/tests/ui/issues/issue-9951.stderr new file mode 100644 index 0000000000000..475f2817914d3 --- /dev/null +++ b/tests/ui/issues/issue-9951.stderr @@ -0,0 +1,12 @@ +warning: method `noop` is never used + --> $DIR/issue-9951.rs:7:6 + | +LL | trait Bar { + | --- method in this trait +LL | fn noop(&self); + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/dead-code/associated-type.rs b/tests/ui/lint/dead-code/associated-type.rs index 1cf66e75a95a5..25106a66e7e36 100644 --- a/tests/ui/lint/dead-code/associated-type.rs +++ b/tests/ui/lint/dead-code/associated-type.rs @@ -15,5 +15,5 @@ impl Foo for Ex { } pub fn main() { - let _x = Ex; + let _x: &dyn Foo::Bar> = &Ex; } diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs index 942c551650032..2d6364aa0cde1 100644 --- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs @@ -17,7 +17,7 @@ struct Bar { // Issue 119267: this should not ICE. #[derive(Debug)] -struct Foo(usize, #[allow(unused)] usize); //~ WARN field `0` is never read +struct Foo(usize, #[allow(unused)] usize); //~ WARN struct `Foo` is never constructed fn main() { Bar { diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr index 06f9b229c18c1..b992005318f2e 100644 --- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr @@ -51,19 +51,13 @@ note: the lint level is defined here LL | #[forbid(dead_code)] | ^^^^^^^^^ -warning: field `0` is never read - --> $DIR/multiple-dead-codes-in-the-same-struct.rs:20:12 +warning: struct `Foo` is never constructed + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:20:8 | LL | struct Foo(usize, #[allow(unused)] usize); - | --- ^^^^^ - | | - | field in this struct + | ^^^ | = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis -help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field - | -LL | struct Foo((), #[allow(unused)] usize); - | ~~ error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/tests/ui/lint/issue-20343.rs b/tests/ui/lint/issue-20343.rs index 000b6398442a3..f0f4eccc676a1 100644 --- a/tests/ui/lint/issue-20343.rs +++ b/tests/ui/lint/issue-20343.rs @@ -22,6 +22,8 @@ impl B { // test for unused code in generics fn baz>() {} + + fn foz>(a: A) { a.dummy(D); } } pub fn main() { @@ -29,4 +31,5 @@ pub fn main() { B::foo(b); B::bar(); B::baz::<()>(); + B::foz::<()>(()); } diff --git a/tests/ui/macros/issue-22463.rs b/tests/ui/macros/issue-22463.rs index fdf5a2fca7255..8f7b27cb9a056 100644 --- a/tests/ui/macros/issue-22463.rs +++ b/tests/ui/macros/issue-22463.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass macro_rules! items { () => { type A = (); diff --git a/tests/ui/methods/method-lookup-order.rs b/tests/ui/methods/method-lookup-order.rs index 986fe103cdc79..5a46cf35dec0e 100644 --- a/tests/ui/methods/method-lookup-order.rs +++ b/tests/ui/methods/method-lookup-order.rs @@ -1,6 +1,7 @@ // ignore-tidy-linelength // run-pass +#![allow(dead_code)] // There are five cfg's below. I explored the set of all non-empty combinations // of the below five cfg's, which is 2^5 - 1 = 31 combinations. diff --git a/tests/ui/methods/method-recursive-blanket-impl.rs b/tests/ui/methods/method-recursive-blanket-impl.rs index a2db75b4e85d8..e7e83cbec7756 100644 --- a/tests/ui/methods/method-recursive-blanket-impl.rs +++ b/tests/ui/methods/method-recursive-blanket-impl.rs @@ -11,7 +11,7 @@ use std::marker::Sized; // Note: this must be generic for the problem to show up -trait Foo { +trait Foo { //~ WARN trait `Foo` is never used fn foo(&self, a: A); } diff --git a/tests/ui/methods/method-recursive-blanket-impl.stderr b/tests/ui/methods/method-recursive-blanket-impl.stderr new file mode 100644 index 0000000000000..9797a8f6c8308 --- /dev/null +++ b/tests/ui/methods/method-recursive-blanket-impl.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/method-recursive-blanket-impl.rs:14:7 + | +LL | trait Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/methods/method-two-trait-defer-resolution-2.rs b/tests/ui/methods/method-two-trait-defer-resolution-2.rs index fc5766da9714b..d6076126732bc 100644 --- a/tests/ui/methods/method-two-trait-defer-resolution-2.rs +++ b/tests/ui/methods/method-two-trait-defer-resolution-2.rs @@ -14,7 +14,7 @@ trait Foo { fn foo(&self) -> isize; } -trait MyCopy { fn foo(&self) { } } +trait MyCopy { fn foo(&self) { } } //~ WARN method `foo` is never used impl MyCopy for i32 { } impl Foo for Vec { diff --git a/tests/ui/methods/method-two-trait-defer-resolution-2.stderr b/tests/ui/methods/method-two-trait-defer-resolution-2.stderr new file mode 100644 index 0000000000000..4501ea5d24334 --- /dev/null +++ b/tests/ui/methods/method-two-trait-defer-resolution-2.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/method-two-trait-defer-resolution-2.rs:17:19 + | +LL | trait MyCopy { fn foo(&self) { } } + | ------ ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs index d820d2ad08ae8..2fd6c3bfab868 100644 --- a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs +++ b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs @@ -4,7 +4,7 @@ // pretty-expanded FIXME #23616 -trait A { +trait A { //~ WARN trait `A` is never used fn foo(self); } diff --git a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr new file mode 100644 index 0000000000000..0a60c6242bb2d --- /dev/null +++ b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr @@ -0,0 +1,10 @@ +warning: trait `A` is never used + --> $DIR/method-two-traits-distinguished-via-where-clause.rs:7:7 + | +LL | trait A { + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mir/mir_raw_fat_ptr.rs b/tests/ui/mir/mir_raw_fat_ptr.rs index 8e5a2043dc696..e141aa03aa985 100644 --- a/tests/ui/mir/mir_raw_fat_ptr.rs +++ b/tests/ui/mir/mir_raw_fat_ptr.rs @@ -98,7 +98,7 @@ fn assert_inorder(a: &[T], } } -trait Foo { fn foo(&self) -> usize; } +trait Foo { fn foo(&self) -> usize; } //~ WARN method `foo` is never used impl Foo for T { fn foo(&self) -> usize { mem::size_of::() diff --git a/tests/ui/mir/mir_raw_fat_ptr.stderr b/tests/ui/mir/mir_raw_fat_ptr.stderr new file mode 100644 index 0000000000000..a9e9dd66ebdfa --- /dev/null +++ b/tests/ui/mir/mir_raw_fat_ptr.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/mir_raw_fat_ptr.rs:101:16 + | +LL | trait Foo { fn foo(&self) -> usize; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/moves/issue-22536-copy-mustnt-zero.rs b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs index 017f36484c1cf..b3fc1a56f882f 100644 --- a/tests/ui/moves/issue-22536-copy-mustnt-zero.rs +++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs @@ -5,7 +5,7 @@ trait Resources { type Buffer: Copy; - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } struct BufferHandle { diff --git a/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr b/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr new file mode 100644 index 0000000000000..b1fcdfa44c33d --- /dev/null +++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr @@ -0,0 +1,13 @@ +warning: method `foo` is never used + --> $DIR/issue-22536-copy-mustnt-zero.rs:8:8 + | +LL | trait Resources { + | --------- method in this trait +LL | type Buffer: Copy; +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed index 45c7e07a26471..52046a8ab693d 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait TraitWithAType { type Item: ?Sized; } diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs index c3e958f498390..96620c0abda34 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait TraitWithAType { type Item; } diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr index cd2aa9fdbe3e4..9bb770ce43199 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr @@ -1,12 +1,12 @@ error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/assoc_type_bounds_implicit_sized.rs:8:17 + --> $DIR/assoc_type_bounds_implicit_sized.rs:9:17 | LL | type Item = dyn Trait; | ^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)` note: required by a bound in `TraitWithAType::Item` - --> $DIR/assoc_type_bounds_implicit_sized.rs:3:5 + --> $DIR/assoc_type_bounds_implicit_sized.rs:4:5 | LL | type Item; | ^^^^^^^^^^ required by this bound in `TraitWithAType::Item` diff --git a/tests/ui/overloaded/issue-14958.rs b/tests/ui/overloaded/issue-14958.rs index a12564ca9c0ee..80abf5e4e7689 100644 --- a/tests/ui/overloaded/issue-14958.rs +++ b/tests/ui/overloaded/issue-14958.rs @@ -3,7 +3,7 @@ #![feature(fn_traits, unboxed_closures)] -trait Foo { fn dummy(&self) { }} +trait Foo { fn dummy(&self) { }} //~ WARN method `dummy` is never used struct Bar; diff --git a/tests/ui/overloaded/issue-14958.stderr b/tests/ui/overloaded/issue-14958.stderr new file mode 100644 index 0000000000000..cc97730239c30 --- /dev/null +++ b/tests/ui/overloaded/issue-14958.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-14958.rs:6:16 + | +LL | trait Foo { fn dummy(&self) { }} + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/overloaded/overloaded-index-in-field.rs b/tests/ui/overloaded/overloaded-index-in-field.rs index 8a1fa7deb9996..0dc45ea8ca2b8 100644 --- a/tests/ui/overloaded/overloaded-index-in-field.rs +++ b/tests/ui/overloaded/overloaded-index-in-field.rs @@ -27,7 +27,7 @@ impl Index for Foo { trait Int { fn get(self) -> isize; - fn get_from_ref(&self) -> isize; + fn get_from_ref(&self) -> isize; //~ WARN methods `get_from_ref` and `inc` are never used fn inc(&mut self); } diff --git a/tests/ui/overloaded/overloaded-index-in-field.stderr b/tests/ui/overloaded/overloaded-index-in-field.stderr new file mode 100644 index 0000000000000..10c0a3faeb59a --- /dev/null +++ b/tests/ui/overloaded/overloaded-index-in-field.stderr @@ -0,0 +1,15 @@ +warning: methods `get_from_ref` and `inc` are never used + --> $DIR/overloaded-index-in-field.rs:30:8 + | +LL | trait Int { + | --- methods in this trait +LL | fn get(self) -> isize; +LL | fn get_from_ref(&self) -> isize; + | ^^^^^^^^^^^^ +LL | fn inc(&mut self); + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/parser/parse-assoc-type-lt.rs b/tests/ui/parser/parse-assoc-type-lt.rs index d3fe6079a5d2a..913fcd920bdb6 100644 --- a/tests/ui/parser/parse-assoc-type-lt.rs +++ b/tests/ui/parser/parse-assoc-type-lt.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/parser/suggest-assoc-const.fixed b/tests/ui/parser/suggest-assoc-const.fixed index 259f37b23a584..4229135ebb23b 100644 --- a/tests/ui/parser/suggest-assoc-const.fixed +++ b/tests/ui/parser/suggest-assoc-const.fixed @@ -1,5 +1,6 @@ // Issue: 101797, Suggest associated const for incorrect use of let in traits // run-rustfix +#![allow(dead_code)] trait Trait { const _X: i32; //~^ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-assoc-const.rs b/tests/ui/parser/suggest-assoc-const.rs index c7be712ec076e..0cf695bd40aff 100644 --- a/tests/ui/parser/suggest-assoc-const.rs +++ b/tests/ui/parser/suggest-assoc-const.rs @@ -1,5 +1,6 @@ // Issue: 101797, Suggest associated const for incorrect use of let in traits // run-rustfix +#![allow(dead_code)] trait Trait { let _X: i32; //~^ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-assoc-const.stderr b/tests/ui/parser/suggest-assoc-const.stderr index 7ba1dbdff7e59..6e29fad98d466 100644 --- a/tests/ui/parser/suggest-assoc-const.stderr +++ b/tests/ui/parser/suggest-assoc-const.stderr @@ -1,5 +1,5 @@ error: non-item in item list - --> $DIR/suggest-assoc-const.rs:4:5 + --> $DIR/suggest-assoc-const.rs:5:5 | LL | let _X: i32; | ^^^ help: consider using `const` instead of `let` for associated const: `const` diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed index 63704735490fa..81ee6cdf0a722 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn bar() {} //~ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs index 4650b05e20ce8..c8f525fc4f0ad 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn bar() {}; //~ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr index c716d5908ea11..396c76ac85f2f 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -1,5 +1,5 @@ error: non-item in item list - --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:4:16 + --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:5:16 | LL | trait Foo { | - item list starts here diff --git a/tests/ui/pattern/issue-22546.rs b/tests/ui/pattern/issue-22546.rs index c26e457f9e452..8a0f51d0b84b9 100644 --- a/tests/ui/pattern/issue-22546.rs +++ b/tests/ui/pattern/issue-22546.rs @@ -15,7 +15,7 @@ impl Foo { } } -trait Tr { +trait Tr { //~ WARN trait `Tr` is never used type U; } diff --git a/tests/ui/pattern/issue-22546.stderr b/tests/ui/pattern/issue-22546.stderr new file mode 100644 index 0000000000000..e067a95e4226c --- /dev/null +++ b/tests/ui/pattern/issue-22546.stderr @@ -0,0 +1,10 @@ +warning: trait `Tr` is never used + --> $DIR/issue-22546.rs:18:7 + | +LL | trait Tr { + | ^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed index 79b6a6516ab26..6de7b865a9914 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] pub mod a { pub use self::b::Trait; diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.rs b/tests/ui/privacy/sealed-traits/re-exported-trait.rs index 5f96dfdcbd6c4..bf07d666dff89 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.rs +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] pub mod a { pub use self::b::Trait; diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr index 9f2291e6825a6..6e2f36e3f381d 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr @@ -1,11 +1,11 @@ error[E0603]: module `b` is private - --> $DIR/re-exported-trait.rs:11:9 + --> $DIR/re-exported-trait.rs:12:9 | LL | impl a::b::Trait for S {} | ^ private module | note: the module `b` is defined here - --> $DIR/re-exported-trait.rs:5:5 + --> $DIR/re-exported-trait.rs:6:5 | LL | mod b { | ^^^^^ diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed index ae5f9f86726f3..a61c868ed0a1a 100644 --- a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed @@ -1,6 +1,7 @@ // run-rustfix #[derive(Debug)] //~ ERROR `derive` attribute cannot be used at crate level +#[allow(dead_code)] struct Test {} fn main() {} diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs index 639c64f8827c5..403f4470de77b 100644 --- a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs @@ -1,6 +1,7 @@ // run-rustfix #![derive(Debug)] //~ ERROR `derive` attribute cannot be used at crate level +#[allow(dead_code)] struct Test {} fn main() {} diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr index f62cdd14b873f..09908160542d4 100644 --- a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr @@ -3,6 +3,7 @@ error: `derive` attribute cannot be used at crate level | LL | #![derive(Debug)] | ^^^^^^^^^^^^^^^^^ +LL | #[allow(dead_code)] LL | struct Test {} | ---- the inner attribute doesn't annotate this struct | diff --git a/tests/ui/regions/regions-no-variance-from-fn-generics.rs b/tests/ui/regions/regions-no-variance-from-fn-generics.rs index 76706a8278197..a455d4efd71b5 100644 --- a/tests/ui/regions/regions-no-variance-from-fn-generics.rs +++ b/tests/ui/regions/regions-no-variance-from-fn-generics.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Issue #12856: a lifetime formal binding introduced by a generic fn // should not upset the variance inference for actual occurrences of diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed index e730f94660bbd..a7ab88fe99357 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![deny(unused_qualifications)] #![feature(unsized_fn_params)] diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs index 641c892e3de9a..05936b191ffea 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![deny(unused_qualifications)] #![feature(unsized_fn_params)] diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr index d9c7fd21871ba..bcda721071235 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr @@ -1,11 +1,11 @@ error: unnecessary qualification - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:12:6 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:13:6 | LL | impl ops::Index for A { | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:3:9 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:4:9 | LL | #![deny(unused_qualifications)] | ^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL + impl Index for A { | error: unnecessary qualification - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:28:6 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:29:6 | LL | impl inner::Trait for () {} | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr new file mode 100644 index 0000000000000..4a219ff8b5562 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:22:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr new file mode 100644 index 0000000000000..4a219ff8b5562 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:22:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs index c7665affb992b..c8eee9835fed3 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -19,7 +19,7 @@ trait Bad { } trait Good { - fn good_virt(&self) -> char { + fn good_virt(&self) -> char { //~ WARN methods `good_virt` and `good_indirect` are never used panic!() } fn good_indirect(&self) -> char { diff --git a/tests/ui/rust-2018/issue-51008-1.rs b/tests/ui/rust-2018/issue-51008-1.rs index da7b8ef65c566..67dfbf6460133 100644 --- a/tests/ui/rust-2018/issue-51008-1.rs +++ b/tests/ui/rust-2018/issue-51008-1.rs @@ -2,7 +2,7 @@ // being incorrectly considered part of the "elided lifetimes" from // the impl. // -// run-pass +// check-pass trait A { diff --git a/tests/ui/rust-2018/issue-51008.rs b/tests/ui/rust-2018/issue-51008.rs index 56517b9adee65..f9e4bc14ec82c 100644 --- a/tests/ui/rust-2018/issue-51008.rs +++ b/tests/ui/rust-2018/issue-51008.rs @@ -2,7 +2,7 @@ // being incorrectly considered part of the "elided lifetimes" from // the impl. // -// run-pass +// check-pass trait A { diff --git a/tests/ui/sized/coinductive-2.rs b/tests/ui/sized/coinductive-2.rs index 212274d2e4b6c..43a5a28f710a7 100644 --- a/tests/ui/sized/coinductive-2.rs +++ b/tests/ui/sized/coinductive-2.rs @@ -11,7 +11,7 @@ impl CollectionFactory for Vec<()> { type Collection = Vec; } -trait Collection: Sized { +trait Collection: Sized { //~ WARN trait `Collection` is never used fn push(&mut self, v: T); } diff --git a/tests/ui/sized/coinductive-2.stderr b/tests/ui/sized/coinductive-2.stderr new file mode 100644 index 0000000000000..1390b1f8d7bf1 --- /dev/null +++ b/tests/ui/sized/coinductive-2.stderr @@ -0,0 +1,10 @@ +warning: trait `Collection` is never used + --> $DIR/coinductive-2.rs:14:7 + | +LL | trait Collection: Sized { + | ^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.rs b/tests/ui/specialization/assoc-ty-graph-cycle.rs index fc39b553a61ac..bec8cc187b4ab 100644 --- a/tests/ui/specialization/assoc-ty-graph-cycle.rs +++ b/tests/ui/specialization/assoc-ty-graph-cycle.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Make sure we don't crash with a cycle error during coherence. diff --git a/tests/ui/specialization/defaultimpl/out-of-order.rs b/tests/ui/specialization/defaultimpl/out-of-order.rs index 13258ac8c9fe6..94b3905178fa8 100644 --- a/tests/ui/specialization/defaultimpl/out-of-order.rs +++ b/tests/ui/specialization/defaultimpl/out-of-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that you can list the more specific impl before the more general one. diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.rs b/tests/ui/specialization/defaultimpl/overlap-projection.rs index 0add4d5516c7b..46f54c466a831 100644 --- a/tests/ui/specialization/defaultimpl/overlap-projection.rs +++ b/tests/ui/specialization/defaultimpl/overlap-projection.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is diff --git a/tests/ui/specialization/specialization-out-of-order.rs b/tests/ui/specialization/specialization-out-of-order.rs index cb7563e2760c2..66e6c3c9eab31 100644 --- a/tests/ui/specialization/specialization-out-of-order.rs +++ b/tests/ui/specialization/specialization-out-of-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that you can list the more specific impl before the more general one. diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs index b07efb2a5c1cd..cd21eab24c0b7 100644 --- a/tests/ui/specialization/specialization-overlap-projection.rs +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is diff --git a/tests/ui/specialization/specialization-supertraits.rs b/tests/ui/specialization/specialization-supertraits.rs index fb85d8019218a..d0c9dbb1d4014 100644 --- a/tests/ui/specialization/specialization-supertraits.rs +++ b/tests/ui/specialization/specialization-supertraits.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(specialization)] //~ WARN the feature `specialization` is incomplete diff --git a/tests/ui/statics/static-impl.rs b/tests/ui/statics/static-impl.rs index e7bdb38ee62c9..9e2db7e0caf50 100644 --- a/tests/ui/statics/static-impl.rs +++ b/tests/ui/statics/static-impl.rs @@ -35,7 +35,7 @@ impl uint_utils for usize { trait vec_utils { fn length_(&self, ) -> usize; - fn iter_(&self, f: F) where F: FnMut(&T); + fn iter_(&self, f: F) where F: FnMut(&T); //~ WARN method `iter_` is never used fn map_(&self, f: F) -> Vec where F: FnMut(&T) -> U; } diff --git a/tests/ui/statics/static-impl.stderr b/tests/ui/statics/static-impl.stderr new file mode 100644 index 0000000000000..83c3ffbefe1f2 --- /dev/null +++ b/tests/ui/statics/static-impl.stderr @@ -0,0 +1,13 @@ +warning: method `iter_` is never used + --> $DIR/static-impl.rs:38:8 + | +LL | trait vec_utils { + | --------- method in this trait +LL | fn length_(&self, ) -> usize; +LL | fn iter_(&self, f: F) where F: FnMut(&T); + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs b/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs index 0f535523dcc06..4a8289cb24284 100644 --- a/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs +++ b/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs @@ -32,7 +32,7 @@ fn assert_inorder(a: &[T]) { } } -trait Foo { fn foo(&self) -> usize; } +trait Foo { fn foo(&self) -> usize; } //~ WARN method `foo` is never used impl Foo for T { fn foo(&self) -> usize { mem::size_of::() diff --git a/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr b/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr new file mode 100644 index 0000000000000..670fa5bb9224b --- /dev/null +++ b/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/raw-fat-ptr.rs:35:16 + | +LL | trait Foo { fn foo(&self) -> usize; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/structs-enums/enum-null-pointer-opt.rs b/tests/ui/structs-enums/enum-null-pointer-opt.rs index 356f8a6dd36f6..21564eeec29e3 100644 --- a/tests/ui/structs-enums/enum-null-pointer-opt.rs +++ b/tests/ui/structs-enums/enum-null-pointer-opt.rs @@ -7,7 +7,7 @@ use std::ptr::NonNull; use std::rc::Rc; use std::sync::Arc; -trait Trait { fn dummy(&self) { } } +trait Trait { fn dummy(&self) { } } //~ WARN method `dummy` is never used trait Mirror { type Image; } impl Mirror for T { type Image = T; } struct ParamTypeStruct(#[allow(dead_code)] T); diff --git a/tests/ui/structs-enums/enum-null-pointer-opt.stderr b/tests/ui/structs-enums/enum-null-pointer-opt.stderr new file mode 100644 index 0000000000000..64e93ffaffd60 --- /dev/null +++ b/tests/ui/structs-enums/enum-null-pointer-opt.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/enum-null-pointer-opt.rs:10:18 + | +LL | trait Trait { fn dummy(&self) { } } + | ----- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/suggestions/bound-suggestions.fixed b/tests/ui/suggestions/bound-suggestions.fixed index 17a019c69849f..ef61fb9ad325f 100644 --- a/tests/ui/suggestions/bound-suggestions.fixed +++ b/tests/ui/suggestions/bound-suggestions.fixed @@ -40,26 +40,31 @@ fn test_many_bounds_where(x: X) where X: Sized + std::fmt::Debug, X: Sized { //~^ ERROR doesn't implement } +#[allow(dead_code)] trait Foo: Sized { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bar: std::fmt::Display + Sized { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Baz: Sized where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Qux: Sized where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bat: std::fmt::Display + Sized { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time diff --git a/tests/ui/suggestions/bound-suggestions.rs b/tests/ui/suggestions/bound-suggestions.rs index 86f708d42f5e7..6d17fae6a088e 100644 --- a/tests/ui/suggestions/bound-suggestions.rs +++ b/tests/ui/suggestions/bound-suggestions.rs @@ -40,26 +40,31 @@ fn test_many_bounds_where(x: X) where X: Sized, X: Sized { //~^ ERROR doesn't implement } +#[allow(dead_code)] trait Foo { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bar: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Baz where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Qux where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bat: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr index 7e58ccd461d19..4965e7439f849 100644 --- a/tests/ui/suggestions/bound-suggestions.stderr +++ b/tests/ui/suggestions/bound-suggestions.stderr @@ -71,7 +71,7 @@ LL | fn test_many_bounds_where(x: X) where X: Sized + std::fmt::Debug, X: Siz | +++++++++++++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:44:46 + --> $DIR/bound-suggestions.rs:45:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time @@ -84,7 +84,7 @@ LL | trait Foo: Sized { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:49:46 + --> $DIR/bound-suggestions.rs:51:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time @@ -97,7 +97,7 @@ LL | trait Bar: std::fmt::Display + Sized { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:54:46 + --> $DIR/bound-suggestions.rs:57:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time @@ -110,7 +110,7 @@ LL | trait Baz: Sized where Self: std::fmt::Display { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:59:46 + --> $DIR/bound-suggestions.rs:63:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time @@ -123,7 +123,7 @@ LL | trait Qux: Sized where Self: std::fmt::Display { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:64:46 + --> $DIR/bound-suggestions.rs:69:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/suggestions/constrain-trait.fixed b/tests/ui/suggestions/constrain-trait.fixed index f292f27f0f342..f7360efe4c527 100644 --- a/tests/ui/suggestions/constrain-trait.fixed +++ b/tests/ui/suggestions/constrain-trait.fixed @@ -1,5 +1,6 @@ // run-rustfix // check-only +#![allow(dead_code)] #[derive(Debug)] struct Demo { diff --git a/tests/ui/suggestions/constrain-trait.rs b/tests/ui/suggestions/constrain-trait.rs index 99ccf7a7f3bdf..799100669b654 100644 --- a/tests/ui/suggestions/constrain-trait.rs +++ b/tests/ui/suggestions/constrain-trait.rs @@ -1,5 +1,6 @@ // run-rustfix // check-only +#![allow(dead_code)] #[derive(Debug)] struct Demo { diff --git a/tests/ui/suggestions/constrain-trait.stderr b/tests/ui/suggestions/constrain-trait.stderr index a26f86917bc1f..b28972ecde041 100644 --- a/tests/ui/suggestions/constrain-trait.stderr +++ b/tests/ui/suggestions/constrain-trait.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `get_a` found for reference `&Self` in the current scope - --> $DIR/constrain-trait.rs:15:31 + --> $DIR/constrain-trait.rs:16:31 | LL | println!("{:?}", self.get_a()); | ^^^^^ method not found in `&Self` @@ -11,7 +11,7 @@ LL | trait UseString: std::fmt::Debug + GetString { | +++++++++++ error[E0599]: no method named `get_a` found for reference `&Self` in the current scope - --> $DIR/constrain-trait.rs:21:31 + --> $DIR/constrain-trait.rs:22:31 | LL | println!("{:?}", self.get_a()); | ^^^^^ method not found in `&Self` diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed b/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed index 3257ea04c6900..d4a8381fcb146 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed @@ -1,6 +1,7 @@ // Make sure we suggest the bound `T: 'a` in the correct scope: // trait, impl or associated fn. // run-rustfix +#![allow(dead_code)] struct Inv<'a>(#[allow(dead_code)] Option<*mut &'a u8>); diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs b/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs index fcc13aad9965e..dc43e2df6ddb0 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs @@ -1,6 +1,7 @@ // Make sure we suggest the bound `T: 'a` in the correct scope: // trait, impl or associated fn. // run-rustfix +#![allow(dead_code)] struct Inv<'a>(#[allow(dead_code)] Option<*mut &'a u8>); diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr b/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr index d3ca2cc116228..91054472c04d4 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `Self` may not live long enough - --> $DIR/type-param-bound-scope.rs:11:9 + --> $DIR/type-param-bound-scope.rs:12:9 | LL | trait Trait1<'a>: Sized { | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... @@ -13,7 +13,7 @@ LL | trait Trait1<'a>: Sized where Self: 'a { | ++++++++++++++ error[E0309]: the parameter type `Self` may not live long enough - --> $DIR/type-param-bound-scope.rs:18:9 + --> $DIR/type-param-bound-scope.rs:19:9 | LL | fn foo<'a>(self, lt: Inv<'a>) { | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... @@ -26,7 +26,7 @@ LL | fn foo<'a>(self, lt: Inv<'a>) where Self: 'a { | ++++++++++++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:25:9 + --> $DIR/type-param-bound-scope.rs:26:9 | LL | fn foo<'a>(arg: T, lt: Inv<'a>) { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... @@ -39,7 +39,7 @@ LL | fn foo<'a>(arg: T, lt: Inv<'a>) where T: 'a { | +++++++++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:32:9 + --> $DIR/type-param-bound-scope.rs:33:9 | LL | trait Trait4<'a> { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... @@ -53,7 +53,7 @@ LL | fn foo(arg: T, lt: Inv<'a>) { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:42:9 + --> $DIR/type-param-bound-scope.rs:43:9 | LL | impl<'a, T> Trait5<'a> for T { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed index f32c61a99bb8c..90bc10d34c611 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs index d7725f4a3743d..34673852a9b53 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr index 6dc512223d1b0..23a75154f2008 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18 + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:17:18 | LL | struct Wrapper(T); | - this field does not implement `Copy` @@ -8,7 +8,7 @@ LL | impl Copy for Wrapper> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the `Copy` impl for `OnlyCopyIfDisplay` requires that `S: std::fmt::Display` - --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19 + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:5:19 | LL | struct Wrapper(T); | ^ diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed index 1139b315313fc..ff84e42c9470b 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs index 19549248efc23..35d0a9dda7914 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr index fd38d4c64b44c..c9f277fb3501a 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-manual-copy-impl.rs:6:18 + --> $DIR/missing-bound-in-manual-copy-impl.rs:7:18 | LL | struct Wrapper(T); | - this field does not implement `Copy` diff --git a/tests/ui/suggestions/missing-trait-item.fixed b/tests/ui/suggestions/missing-trait-item.fixed index a1cf359ec9124..ded4ec1976067 100644 --- a/tests/ui/suggestions/missing-trait-item.fixed +++ b/tests/ui/suggestions/missing-trait-item.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait T { unsafe fn foo(a: &usize, b: &usize) -> usize; diff --git a/tests/ui/suggestions/missing-trait-item.rs b/tests/ui/suggestions/missing-trait-item.rs index b4fca25ba2f11..de8974037ac99 100644 --- a/tests/ui/suggestions/missing-trait-item.rs +++ b/tests/ui/suggestions/missing-trait-item.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait T { unsafe fn foo(a: &usize, b: &usize) -> usize; diff --git a/tests/ui/suggestions/missing-trait-item.stderr b/tests/ui/suggestions/missing-trait-item.stderr index 4a9d7b472c93a..298d0d16438be 100644 --- a/tests/ui/suggestions/missing-trait-item.stderr +++ b/tests/ui/suggestions/missing-trait-item.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `foo`, `bar` - --> $DIR/missing-trait-item.rs:10:5 + --> $DIR/missing-trait-item.rs:11:5 | LL | unsafe fn foo(a: &usize, b: &usize) -> usize; | --------------------------------------------- `foo` from trait @@ -10,7 +10,7 @@ LL | impl T for () {} | ^^^^^^^^^^^^^ missing `foo`, `bar` in implementation error[E0046]: not all trait items implemented, missing: `foo`, `bar` - --> $DIR/missing-trait-item.rs:12:5 + --> $DIR/missing-trait-item.rs:13:5 | LL | unsafe fn foo(a: &usize, b: &usize) -> usize; | --------------------------------------------- `foo` from trait diff --git a/tests/ui/threads-sendsync/sync-send-atomics.rs b/tests/ui/threads-sendsync/sync-send-atomics.rs index 0466f4f0e9ddc..6b260311a50a7 100644 --- a/tests/ui/threads-sendsync/sync-send-atomics.rs +++ b/tests/ui/threads-sendsync/sync-send-atomics.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 diff --git a/tests/ui/traits/alias/bounds.rs b/tests/ui/traits/alias/bounds.rs index b97eb38c5af8d..7b1920bc8f27c 100644 --- a/tests/ui/traits/alias/bounds.rs +++ b/tests/ui/traits/alias/bounds.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; -trait Empty {} +trait Empty {} //~ WARN trait `Empty` is never used trait EmptyAlias = Empty; trait CloneDefault = Clone + Default; trait SendSyncAlias = Send + Sync; diff --git a/tests/ui/traits/alias/bounds.stderr b/tests/ui/traits/alias/bounds.stderr new file mode 100644 index 0000000000000..7fb8e918da36d --- /dev/null +++ b/tests/ui/traits/alias/bounds.stderr @@ -0,0 +1,10 @@ +warning: trait `Empty` is never used + --> $DIR/bounds.rs:7:7 + | +LL | trait Empty {} + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/alias/syntax.rs b/tests/ui/traits/alias/syntax.rs index 17557a51aa723..50c77d33c6bce 100644 --- a/tests/ui/traits/alias/syntax.rs +++ b/tests/ui/traits/alias/syntax.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] diff --git a/tests/ui/traits/bound/impl-comparison-duplicates.rs b/tests/ui/traits/bound/impl-comparison-duplicates.rs index de6c2afa2bbe1..a59662c2797ff 100644 --- a/tests/ui/traits/bound/impl-comparison-duplicates.rs +++ b/tests/ui/traits/bound/impl-comparison-duplicates.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Tests that type parameter bounds on an implementation need not match the // trait exactly, as long as the implementation doesn't demand *more* bounds // than the trait. diff --git a/tests/ui/traits/bound/recursion.rs b/tests/ui/traits/bound/recursion.rs index 0023ff654e84c..767040dff3f73 100644 --- a/tests/ui/traits/bound/recursion.rs +++ b/tests/ui/traits/bound/recursion.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait I { fn i(&self) -> Self; } diff --git a/tests/ui/traits/composition-trivial.rs b/tests/ui/traits/composition-trivial.rs index 90e5dcd68e8c4..41e6a55607449 100644 --- a/tests/ui/traits/composition-trivial.rs +++ b/tests/ui/traits/composition-trivial.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/traits/cycle-generic-bound.rs b/tests/ui/traits/cycle-generic-bound.rs index 9241f3789d72a..77685c26da242 100644 --- a/tests/ui/traits/cycle-generic-bound.rs +++ b/tests/ui/traits/cycle-generic-bound.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Regression test for #15477. This test just needs to compile. // pretty-expanded FIXME #23616 diff --git a/tests/ui/traits/default-method/bound-subst4.rs b/tests/ui/traits/default-method/bound-subst4.rs index ef13306458255..6bc4cf0ef805c 100644 --- a/tests/ui/traits/default-method/bound-subst4.rs +++ b/tests/ui/traits/default-method/bound-subst4.rs @@ -4,7 +4,7 @@ trait A { fn g(&self, x: usize) -> usize { x } - fn h(&self, x: T) { } + fn h(&self, x: T) { } //~ WARN method `h` is never used } impl A for isize { } diff --git a/tests/ui/traits/default-method/bound-subst4.stderr b/tests/ui/traits/default-method/bound-subst4.stderr new file mode 100644 index 0000000000000..548c46f123322 --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst4.stderr @@ -0,0 +1,13 @@ +warning: method `h` is never used + --> $DIR/bound-subst4.rs:7:8 + | +LL | trait A { + | - method in this trait +LL | fn g(&self, x: usize) -> usize { x } +LL | fn h(&self, x: T) { } + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/default-method/mut.rs b/tests/ui/traits/default-method/mut.rs index 5f8e983b09cfb..3294b96561fd1 100644 --- a/tests/ui/traits/default-method/mut.rs +++ b/tests/ui/traits/default-method/mut.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_assignments)] // pretty-expanded FIXME #23616 diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.rs b/tests/ui/traits/impl-inherent-prefer-over-trait.rs index 82760788897a5..f03e730d091eb 100644 --- a/tests/ui/traits/impl-inherent-prefer-over-trait.rs +++ b/tests/ui/traits/impl-inherent-prefer-over-trait.rs @@ -3,7 +3,7 @@ struct Foo; trait Trait { - fn bar(&self); + fn bar(&self); //~ WARN method `bar` is never used } // Inherent impls should be preferred over trait ones. diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.stderr b/tests/ui/traits/impl-inherent-prefer-over-trait.stderr new file mode 100644 index 0000000000000..f0bb21402d873 --- /dev/null +++ b/tests/ui/traits/impl-inherent-prefer-over-trait.stderr @@ -0,0 +1,12 @@ +warning: method `bar` is never used + --> $DIR/impl-inherent-prefer-over-trait.rs:6:8 + | +LL | trait Trait { + | ----- method in this trait +LL | fn bar(&self); + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.rs b/tests/ui/traits/impl-object-overlap-issue-23853.rs index e490967b69047..c0d3af11443d4 100644 --- a/tests/ui/traits/impl-object-overlap-issue-23853.rs +++ b/tests/ui/traits/impl-object-overlap-issue-23853.rs @@ -5,7 +5,7 @@ // including `Bar`, but the object type `Bar` also implicitly supplies // this context. -trait Foo { fn dummy(&self) { } } +trait Foo { fn dummy(&self) { } } //~ WARN method `dummy` is never used trait Bar: Foo { } diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.stderr b/tests/ui/traits/impl-object-overlap-issue-23853.stderr new file mode 100644 index 0000000000000..9fa7a36816e4d --- /dev/null +++ b/tests/ui/traits/impl-object-overlap-issue-23853.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/impl-object-overlap-issue-23853.rs:8:16 + | +LL | trait Foo { fn dummy(&self) { } } + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/impl.rs b/tests/ui/traits/impl.rs index f512d91ebeb4a..7bec1b6c9ff4f 100644 --- a/tests/ui/traits/impl.rs +++ b/tests/ui/traits/impl.rs @@ -9,7 +9,7 @@ use traitimpl::Bar; static mut COUNT: usize = 1; trait T { - fn t(&self) {} + fn t(&self) {} //~ WARN method `t` is never used } impl<'a> dyn T+'a { diff --git a/tests/ui/traits/impl.stderr b/tests/ui/traits/impl.stderr new file mode 100644 index 0000000000000..98b6fb03d836f --- /dev/null +++ b/tests/ui/traits/impl.stderr @@ -0,0 +1,12 @@ +warning: method `t` is never used + --> $DIR/impl.rs:12:8 + | +LL | trait T { + | - method in this trait +LL | fn t(&self) {} + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/issue-38033.rs b/tests/ui/traits/issue-38033.rs index 16b867ec88f17..4d76df1e8d5bc 100644 --- a/tests/ui/traits/issue-38033.rs +++ b/tests/ui/traits/issue-38033.rs @@ -19,7 +19,7 @@ trait IntoFuture { type Item; type Error; - fn into_future(self) -> Self::Future; + fn into_future(self) -> Self::Future; //~ WARN method `into_future` is never used } impl IntoFuture for F { diff --git a/tests/ui/traits/issue-38033.stderr b/tests/ui/traits/issue-38033.stderr new file mode 100644 index 0000000000000..05385e8cf4d9d --- /dev/null +++ b/tests/ui/traits/issue-38033.stderr @@ -0,0 +1,13 @@ +warning: method `into_future` is never used + --> $DIR/issue-38033.rs:22:8 + | +LL | trait IntoFuture { + | ---------- method in this trait +... +LL | fn into_future(self) -> Self::Future; + | ^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/issue-56488.rs b/tests/ui/traits/issue-56488.rs index e2f3996927b7f..8b68f314c04dd 100644 --- a/tests/ui/traits/issue-56488.rs +++ b/tests/ui/traits/issue-56488.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] diff --git a/tests/ui/traits/issue-59029-2.rs b/tests/ui/traits/issue-59029-2.rs index 2bdb128d8c4c8..fca9f1f13c9de 100644 --- a/tests/ui/traits/issue-59029-2.rs +++ b/tests/ui/traits/issue-59029-2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] trait Svc { type Res; } diff --git a/tests/ui/traits/issue-6128.rs b/tests/ui/traits/issue-6128.rs index 07d92f8f8a016..f5fa0de809a19 100644 --- a/tests/ui/traits/issue-6128.rs +++ b/tests/ui/traits/issue-6128.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; trait Graph { - fn f(&self, _: Edge); + fn f(&self, _: Edge); //~ WARN methods `f` and `g` are never used fn g(&self, _: Node); } diff --git a/tests/ui/traits/issue-6128.stderr b/tests/ui/traits/issue-6128.stderr new file mode 100644 index 0000000000000..c9518ea41ea70 --- /dev/null +++ b/tests/ui/traits/issue-6128.stderr @@ -0,0 +1,14 @@ +warning: methods `f` and `g` are never used + --> $DIR/issue-6128.rs:6:8 + | +LL | trait Graph { + | ----- methods in this trait +LL | fn f(&self, _: Edge); + | ^ +LL | fn g(&self, _: Node); + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs index f845e198aa574..e9ae8ab012a09 100644 --- a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs +++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs @@ -6,7 +6,7 @@ use std::cell::RefCell; -trait Foo { +trait Foo { //~ WARN trait `Foo` is never used fn foo(&self) {} } diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr b/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr new file mode 100644 index 0000000000000..25313a477f7af --- /dev/null +++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/multidispatch-conditional-impl-not-considered.rs:9:7 + | +LL | trait Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/multidispatch-infer-convert-target.rs b/tests/ui/traits/multidispatch-infer-convert-target.rs index 626e1ae71bc2f..a3653dea2cbdf 100644 --- a/tests/ui/traits/multidispatch-infer-convert-target.rs +++ b/tests/ui/traits/multidispatch-infer-convert-target.rs @@ -5,7 +5,7 @@ use std::mem; trait Convert { - fn convert(&self) -> Target; + fn convert(&self) -> Target; //~ WARN method `convert` is never used } impl Convert for i16 { diff --git a/tests/ui/traits/multidispatch-infer-convert-target.stderr b/tests/ui/traits/multidispatch-infer-convert-target.stderr new file mode 100644 index 0000000000000..c8c1b64271950 --- /dev/null +++ b/tests/ui/traits/multidispatch-infer-convert-target.stderr @@ -0,0 +1,12 @@ +warning: method `convert` is never used + --> $DIR/multidispatch-infer-convert-target.rs:8:8 + | +LL | trait Convert { + | ------- method in this trait +LL | fn convert(&self) -> Target; + | ^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.rs b/tests/ui/traits/negative-impls/negative-specializes-negative.rs index 35297ab124ed0..01829e4130115 100644 --- a/tests/ui/traits/negative-impls/negative-specializes-negative.rs +++ b/tests/ui/traits/negative-impls/negative-specializes-negative.rs @@ -3,7 +3,7 @@ // Test a negative impl that "specializes" another negative impl. // -// run-pass +// check-pass trait MyTrait {} diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs index 9825158c2dd38..6486ec3891c68 100644 --- a/tests/ui/traits/trait-upcasting/lifetime.rs +++ b/tests/ui/traits/trait-upcasting/lifetime.rs @@ -7,7 +7,7 @@ trait Foo: PartialEq + std::fmt::Debug + Send + Sync { 10 } - fn z(&self) -> i32 { + fn z(&self) -> i32 { //~ WARN methods `z` and `y` are never used 11 } @@ -21,7 +21,7 @@ trait Bar: Foo { 20 } - fn w(&self) -> i32 { + fn w(&self) -> i32 { //~ WARN method `w` is never used 21 } } diff --git a/tests/ui/traits/trait-upcasting/lifetime.stderr b/tests/ui/traits/trait-upcasting/lifetime.stderr new file mode 100644 index 0000000000000..ca8f9cf63f3e7 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/lifetime.stderr @@ -0,0 +1,25 @@ +warning: methods `z` and `y` are never used + --> $DIR/lifetime.rs:10:8 + | +LL | trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + | --- methods in this trait +... +LL | fn z(&self) -> i32 { + | ^ +... +LL | fn y(&self) -> i32 { + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: method `w` is never used + --> $DIR/lifetime.rs:24:8 + | +LL | trait Bar: Foo { + | --- method in this trait +... +LL | fn w(&self) -> i32 { + | ^ + +warning: 2 warnings emitted + diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs index 9ccfc9306ac0c..5ef65786bb705 100644 --- a/tests/ui/traits/trait-upcasting/replace-vptr.rs +++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs @@ -3,7 +3,7 @@ #![feature(trait_upcasting)] trait A { - fn foo_a(&self); + fn foo_a(&self); //~ WARN method `foo_a` is never used } trait B { @@ -11,7 +11,7 @@ trait B { } trait C: A + B { - fn foo_c(&self); + fn foo_c(&self); //~ WARN method `foo_c` is never used } struct S(i32); diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.stderr b/tests/ui/traits/trait-upcasting/replace-vptr.stderr new file mode 100644 index 0000000000000..823094761b385 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/replace-vptr.stderr @@ -0,0 +1,20 @@ +warning: method `foo_a` is never used + --> $DIR/replace-vptr.rs:6:8 + | +LL | trait A { + | - method in this trait +LL | fn foo_a(&self); + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: method `foo_c` is never used + --> $DIR/replace-vptr.rs:14:8 + | +LL | trait C: A + B { + | - method in this trait +LL | fn foo_c(&self); + | ^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/traits/use-before-def.rs b/tests/ui/traits/use-before-def.rs index 1ee2b941909f4..e52dc53fbab79 100644 --- a/tests/ui/traits/use-before-def.rs +++ b/tests/ui/traits/use-before-def.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(non_camel_case_types)] // Issue #1761 diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs index 74b2ef48533d2..e90c8763d651f 100644 --- a/tests/ui/traits/wf-object/reverse-order.rs +++ b/tests/ui/traits/wf-object/reverse-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. diff --git a/tests/ui/trivial_casts-rpass.rs b/tests/ui/trivial_casts-rpass.rs index 8e49468bf0c45..4653a8df802da 100644 --- a/tests/ui/trivial_casts-rpass.rs +++ b/tests/ui/trivial_casts-rpass.rs @@ -4,7 +4,7 @@ #![allow(trivial_casts, trivial_numeric_casts)] trait Foo { - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } pub struct Bar; diff --git a/tests/ui/trivial_casts-rpass.stderr b/tests/ui/trivial_casts-rpass.stderr new file mode 100644 index 0000000000000..74698b61ab4a4 --- /dev/null +++ b/tests/ui/trivial_casts-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/trivial_casts-rpass.rs:7:8 + | +LL | trait Foo { + | --- method in this trait +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/type-alias-impl-trait/issue-58887.rs b/tests/ui/type-alias-impl-trait/issue-58887.rs index 9675867656a96..68d85ed6b0f9b 100644 --- a/tests/ui/type-alias-impl-trait/issue-58887.rs +++ b/tests/ui/type-alias-impl-trait/issue-58887.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed index 5be6ff8e7e14e..700e4f2542384 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs index d7072aa118161..66ba9b24dac2f 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr index 54e62f34fbaa3..f012120e550d7 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-inherent-impl-ampersand-rust2015.rs:13:17 + --> $DIR/where-clause-inherent-impl-ampersand-rust2015.rs:14:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed index 0f1be586589e2..56682db3b0b43 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed @@ -1,5 +1,6 @@ // edition:2018 // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs index 59f7e472e2d34..5302b2f1576b6 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs @@ -1,5 +1,6 @@ // edition:2018 // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr index 36f3e9ef14527..7d675dd41e904 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-inherent-impl-ampersand-rust2018.rs:14:17 + --> $DIR/where-clause-inherent-impl-ampersand-rust2018.rs:15:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed index 55c7470960eb2..f3adc7e7fad32 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs index 42a35b0216119..1e084e9ad41bb 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr index 92b7a9c2af893..8aa0e52c688db 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-trait-impl-region-2015.rs:10:17 + --> $DIR/where-clause-trait-impl-region-2015.rs:11:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed index 09b96fe5ea42a..dd8074abed728 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed @@ -1,6 +1,8 @@ // run-rustfix // edition:2018 +#![allow(dead_code)] + trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs index 445f38cbee187..4fc9c71b17943 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs @@ -1,6 +1,8 @@ // run-rustfix // edition:2018 +#![allow(dead_code)] + trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr index 63d8b99ed18fb..22940d0b0b18d 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-trait-impl-region-2018.rs:11:17 + --> $DIR/where-clause-trait-impl-region-2018.rs:13:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/where-clauses/issue-50825-1.rs b/tests/ui/where-clauses/issue-50825-1.rs index ee4316029a829..2ee34ad714ede 100644 --- a/tests/ui/where-clauses/issue-50825-1.rs +++ b/tests/ui/where-clauses/issue-50825-1.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // regression test for issue #50825 // Make sure that the `impl` bound (): X is preferred over // the (): X bound in the where clause. diff --git a/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs index ea60fa708764f..65fd2f3096c93 100644 --- a/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs +++ b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Bound { diff --git a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs index 6fc570b9b5b9b..a7ce0590fcd46 100644 --- a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs +++ b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs @@ -3,7 +3,7 @@ // pretty-expanded FIXME #23616 -trait TheTrait { fn dummy(&self) { } } +trait TheTrait { fn dummy(&self) { } } //~ WARN method `dummy` is never used impl TheTrait for &'static isize { } diff --git a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr new file mode 100644 index 0000000000000..a9fe11ea6b316 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/where-clause-early-bound-lifetimes.rs:6:21 + | +LL | trait TheTrait { fn dummy(&self) { } } + | -------- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs index daa3c8dd8e367..8f9c6fbff3d8f 100644 --- a/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs +++ b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs @@ -2,7 +2,7 @@ #![allow(unused_variables)] // pretty-expanded FIXME #23616 -trait Foo { fn dummy(&self, arg: T) { } } +trait Foo { fn dummy(&self, arg: T) { } } //~ WARN method `dummy` is never used trait Bar { fn method(&self) where A: Foo; diff --git a/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr b/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr new file mode 100644 index 0000000000000..0d09cb9de3f6b --- /dev/null +++ b/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/where-clause-method-substituion-rpass.rs:5:19 + | +LL | trait Foo { fn dummy(&self, arg: T) { } } + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed index 2f47c0d91fa96..4e1aa59aac0f0 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed @@ -1,6 +1,8 @@ // check-pass // run-rustfix +#![allow(dead_code)] + trait Trait { // Fine. type Assoc where u32: Copy; diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs index b20aa9398b58f..05b2f8c82a456 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs @@ -1,6 +1,8 @@ // check-pass // run-rustfix +#![allow(dead_code)] + trait Trait { // Fine. type Assoc where u32: Copy; diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr index b4de051845fa6..6ff9d2dd73b5b 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr @@ -1,5 +1,5 @@ warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:13:16 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:15:16 | LL | type Assoc where u32: Copy = (); | ^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:16:17 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:18:17 | LL | type Assoc2 where u32: Copy = () where i32: Copy; | ^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL + type Assoc2 = () where i32: Copy, u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:24:17 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:26:17 | LL | type Assoc2 where u32: Copy, i32: Copy = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed index d171eba50b788..940e2cc8e9750 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![allow(dead_code)] #![feature(associated_type_defaults)] trait Trait { diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs index 59afee65794c4..7001a9245a5f3 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![allow(dead_code)] #![feature(associated_type_defaults)] trait Trait { diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr index a81cb8c8cd62e..9e9967ef7391a 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr @@ -1,5 +1,5 @@ warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-trait.rs:8:16 + --> $DIR/where-clause-placement-assoc-type-in-trait.rs:9:16 | LL | type Assoc where u32: Copy = (); | ^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-trait.rs:11:17 + --> $DIR/where-clause-placement-assoc-type-in-trait.rs:12:17 | LL | type Assoc2 where u32: Copy = () where i32: Copy; | ^^^^^^^^^^^^^^^ From 4451bf4d678c67755c153995d638559a76469af2 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 7 Jan 2024 17:53:20 -0500 Subject: [PATCH 609/676] Use a better set of targets for blessing mir-opt tests --- src/bootstrap/src/core/build_steps/compile.rs | 32 ++- src/bootstrap/src/core/build_steps/test.rs | 119 +++----- src/bootstrap/src/core/builder.rs | 256 ++++++++++-------- src/tools/compiletest/src/runtest.rs | 2 + .../inline/cycle.g.Inline.panic-abort.diff | 21 +- .../inline/cycle.g.Inline.panic-unwind.diff | 29 +- tests/mir-opt/inline/cycle.rs | 4 +- ...cycle_generic.main.Inline.panic-abort.diff | 6 +- ...ycle_generic.main.Inline.panic-unwind.diff | 6 +- .../issue_99325.main.built.after.32bit.mir | 4 +- .../issue_99325.main.built.after.64bit.mir | 4 +- 11 files changed, 220 insertions(+), 263 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index ddbe18ab8388d..3c0d074807d39 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -97,6 +97,20 @@ impl Std { is_for_mir_opt_tests: false, } } + + fn copy_extra_objects( + &self, + builder: &Builder<'_>, + compiler: &Compiler, + target: TargetSelection, + ) -> Vec<(PathBuf, DependencyType)> { + let mut deps = Vec::new(); + if !self.is_for_mir_opt_tests { + deps.extend(copy_third_party_objects(builder, &compiler, target)); + deps.extend(copy_self_contained_objects(builder, &compiler, target)); + } + deps + } } impl Step for Std { @@ -159,8 +173,7 @@ impl Step for Std { { builder.info("WARNING: Using a potentially old libstd. This may not behave well."); - copy_third_party_objects(builder, &compiler, target); - copy_self_contained_objects(builder, &compiler, target); + self.copy_extra_objects(builder, &compiler, target); builder.ensure(StdLink::from_std(self, compiler)); return; @@ -193,15 +206,13 @@ impl Step for Std { // Even if we're not building std this stage, the new sysroot must // still contain the third party objects needed by various targets. - copy_third_party_objects(builder, &compiler, target); - copy_self_contained_objects(builder, &compiler, target); + self.copy_extra_objects(builder, &compiler, target); builder.ensure(StdLink::from_std(self, compiler_to_use)); return; } - target_deps.extend(copy_third_party_objects(builder, &compiler, target)); - target_deps.extend(copy_self_contained_objects(builder, &compiler, target)); + target_deps.extend(self.copy_extra_objects(builder, &compiler, target)); // The LLD wrappers and `rust-lld` are self-contained linking components that can be // necessary to link the stdlib on some targets. We'll also need to copy these binaries to @@ -222,9 +233,12 @@ impl Step for Std { } } + // We build a sysroot for mir-opt tests using the same trick that Miri does: A check build + // with -Zalways-encode-mir. This frees us from the need to have a target linker, and the + // fact that this is a check build integrates nicely with run_cargo. let mut cargo = if self.is_for_mir_opt_tests { - let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustc"); - cargo.arg("-p").arg("std").arg("--crate-type=lib"); + let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "check"); + cargo.rustflag("-Zalways-encode-mir"); std_cargo(builder, target, compiler.stage, &mut cargo); cargo } else { @@ -257,7 +271,7 @@ impl Step for Std { vec![], &libstd_stamp(builder, compiler, target), target_deps, - false, + self.is_for_mir_opt_tests, // is_check false, ); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 04728e2e00dcc..e1a1c416ae993 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -25,7 +25,6 @@ use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::flags::get_completion; use crate::core::config::flags::Subcommand; use crate::core::config::TargetSelection; -use crate::utils; use crate::utils::cache::{Interned, INTERNER}; use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ @@ -38,23 +37,6 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/local/tmp/work"; -// mir-opt tests have different variants depending on whether a target is 32bit or 64bit, and -// blessing them requires blessing with each target. To aid developers, when blessing the mir-opt -// test suite the corresponding target of the opposite pointer size is also blessed. -// -// This array serves as the known mappings between 32bit and 64bit targets. If you're developing on -// a target where a target with the opposite pointer size exists, feel free to add it here. -const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[ - // (32bit, 64bit) - ("i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu"), - ("i686-unknown-linux-musl", "x86_64-unknown-linux-musl"), - ("i686-pc-windows-msvc", "x86_64-pc-windows-msvc"), - ("i686-pc-windows-gnu", "x86_64-pc-windows-gnu"), - // ARM Macs don't have a corresponding 32-bit target that they can (easily) - // build for, so there is no entry for "aarch64-apple-darwin" here. - // Likewise, i686 for macOS is no longer possible to build. -]; - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CrateBootstrap { path: Interned, @@ -1487,46 +1469,19 @@ impl Step for MirOpt { }) }; - // We use custom logic to bless the mir-opt suite: mir-opt tests have multiple variants - // (32bit vs 64bit, and panic=abort vs panic=unwind), and all of them needs to be blessed. - // When blessing, we try best-effort to also bless the other variants, to aid developers. if builder.config.cmd.bless() { - let targets = MIR_OPT_BLESS_TARGET_MAPPING - .iter() - .filter(|(target_32bit, target_64bit)| { - *target_32bit == &*self.target.triple || *target_64bit == &*self.target.triple - }) - .next() - .map(|(target_32bit, target_64bit)| { - let target_32bit = TargetSelection::from_user(target_32bit); - let target_64bit = TargetSelection::from_user(target_64bit); - - // Running compiletest requires a C compiler to be available, but it might not - // have been detected by bootstrap if the target we're testing wasn't in the - // --target flags. - if !builder.cc.borrow().contains_key(&target_32bit) { - utils::cc_detect::find_target(builder, target_32bit); - } - if !builder.cc.borrow().contains_key(&target_64bit) { - utils::cc_detect::find_target(builder, target_64bit); - } - - vec![target_32bit, target_64bit] - }) - .unwrap_or_else(|| { - eprintln!( - "\ -Note that not all variants of mir-opt tests are going to be blessed, as no mapping between -a 32bit and a 64bit target was found for {target}. -You can add that mapping by changing MIR_OPT_BLESS_TARGET_MAPPING in src/bootstrap/test.rs", - target = self.target, - ); - vec![self.target] - }); - - for target in targets { - run(target); + crate::utils::cc_detect::find_target(builder, self.compiler.host); + // All that we really need to do is cover all combinations of 32/64-bit and unwind/abort, + // but while we're at it we might as well flex our cross-compilation support. This + // selection covers all our tier 1 operating systems and architectures using only tier + // 1 targets. + + for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] { + run(TargetSelection::from_user(target)); + } + for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] { + let target = TargetSelection::from_user(target); let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget { compiler: self.compiler, base: target, @@ -1616,27 +1571,27 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target }); } - if suite == "mir-opt" { - builder.ensure(compile::Std::new_for_mir_opt_tests(compiler, target)); - } else { - builder.ensure(compile::Std::new(compiler, target)); - } + // Also provide `rust_test_helpers` for the host. + builder.ensure(TestHelpers { target: compiler.host }); // ensure that `libproc_macro` is available on the host. builder.ensure(compile::Std::new(compiler, compiler.host)); - // Also provide `rust_test_helpers` for the host. - builder.ensure(TestHelpers { target: compiler.host }); - // As well as the target, except for plain wasm32, which can't build it if suite != "mir-opt" && !target.contains("wasm") && !target.contains("emscripten") { builder.ensure(TestHelpers { target }); } - builder.ensure(RemoteCopyLibs { compiler, target }); - let mut cmd = builder.tool_cmd(Tool::Compiletest); + if suite == "mir-opt" { + builder.ensure(compile::Std::new_for_mir_opt_tests(compiler, target)); + } else { + builder.ensure(compile::Std::new(compiler, target)); + } + + builder.ensure(RemoteCopyLibs { compiler, target }); + // compiletest currently has... a lot of arguments, so let's just pass all // of them! @@ -1745,11 +1700,13 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests)); flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string())); - if let Some(linker) = builder.linker(target) { - cmd.arg("--target-linker").arg(linker); - } - if let Some(linker) = builder.linker(compiler.host) { - cmd.arg("--host-linker").arg(linker); + if suite != "mir-opt" { + if let Some(linker) = builder.linker(target) { + cmd.arg("--target-linker").arg(linker); + } + if let Some(linker) = builder.linker(compiler.host) { + cmd.arg("--host-linker").arg(linker); + } } let mut hostflags = flags.clone(); @@ -1936,15 +1893,17 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient)); } - // Running a C compiler on MSVC requires a few env vars to be set, to be - // sure to set them here. - // - // Note that if we encounter `PATH` we make sure to append to our own `PATH` - // rather than stomp over it. - if !builder.config.dry_run() && target.is_msvc() { - for &(ref k, ref v) in builder.cc.borrow()[&target].env() { - if k != "PATH" { - cmd.env(k, v); + if suite != "mir-opt" { + // Running a C compiler on MSVC requires a few env vars to be set, to be + // sure to set them here. + // + // Note that if we encounter `PATH` we make sure to append to our own `PATH` + // rather than stomp over it. + if !builder.config.dry_run() && target.is_msvc() { + for &(ref k, ref v) in builder.cc.borrow()[&target].env() { + if k != "PATH" { + cmd.env(k, v); + } } } } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index dac8393de6b4c..4bb8ed2fa67fb 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1646,76 +1646,12 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_WRAPPER_REAL", existing_wrapper); } - // Dealing with rpath here is a little special, so let's go into some - // detail. First off, `-rpath` is a linker option on Unix platforms - // which adds to the runtime dynamic loader path when looking for - // dynamic libraries. We use this by default on Unix platforms to ensure - // that our nightlies behave the same on Windows, that is they work out - // of the box. This can be disabled by setting `rpath = false` in `[rust]` - // table of `config.toml` - // - // Ok, so the astute might be wondering "why isn't `-C rpath` used - // here?" and that is indeed a good question to ask. This codegen - // option is the compiler's current interface to generating an rpath. - // Unfortunately it doesn't quite suffice for us. The flag currently - // takes no value as an argument, so the compiler calculates what it - // should pass to the linker as `-rpath`. This unfortunately is based on - // the **compile time** directory structure which when building with - // Cargo will be very different than the runtime directory structure. - // - // All that's a really long winded way of saying that if we use - // `-Crpath` then the executables generated have the wrong rpath of - // something like `$ORIGIN/deps` when in fact the way we distribute - // rustc requires the rpath to be `$ORIGIN/../lib`. - // - // So, all in all, to set up the correct rpath we pass the linker - // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it - // fun to pass a flag to a tool to pass a flag to pass a flag to a tool - // to change a flag in a binary? - if self.config.rpath_enabled(target) && helpers::use_host_linker(target) { - let libdir = self.sysroot_libdir_relative(compiler).to_str().unwrap(); - let rpath = if target.contains("apple") { - // Note that we need to take one extra step on macOS to also pass - // `-Wl,-instal_name,@rpath/...` to get things to work right. To - // do that we pass a weird flag to the compiler to get it to do - // so. Note that this is definitely a hack, and we should likely - // flesh out rpath support more fully in the future. - rustflags.arg("-Zosx-rpath-install-name"); - Some(format!("-Wl,-rpath,@loader_path/../{libdir}")) - } else if !target.is_windows() && !target.contains("aix") && !target.contains("xous") { - rustflags.arg("-Clink-args=-Wl,-z,origin"); - Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}")) - } else { - None - }; - if let Some(rpath) = rpath { - rustflags.arg(&format!("-Clink-args={rpath}")); - } - } - cargo.env(profile_var("STRIP"), self.config.rust_strip.to_string()); if let Some(stack_protector) = &self.config.rust_stack_protector { rustflags.arg(&format!("-Zstack-protector={stack_protector}")); } - for arg in linker_args(self, compiler.host, LldThreads::Yes) { - hostflags.arg(&arg); - } - - if let Some(target_linker) = self.linker(target) { - let target = crate::envify(&target.triple); - cargo.env(&format!("CARGO_TARGET_{target}_LINKER"), target_linker); - } - // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not - // `linker_args` here. - for flag in linker_flags(self, target, LldThreads::Yes) { - rustflags.arg(&flag); - } - for arg in linker_args(self, target, LldThreads::Yes) { - rustdocflags.arg(&arg); - } - if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)); } @@ -1731,10 +1667,6 @@ impl<'a> Builder<'a> { if let Some(opt_level) = &self.config.rust_optimize.get_opt_level() { cargo.env(profile_var("OPT_LEVEL"), opt_level); } - if !self.config.dry_run() && self.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz") - { - rustflags.arg("-Clink-arg=-gz"); - } cargo.env( profile_var("DEBUG_ASSERTIONS"), if mode == Mode::Std { @@ -1940,55 +1872,15 @@ impl<'a> Builder<'a> { rustflags.arg("-Wrustc::internal"); } - // Throughout the build Cargo can execute a number of build scripts - // compiling C/C++ code and we need to pass compilers, archivers, flags, etc - // obtained previously to those build scripts. - // Build scripts use either the `cc` crate or `configure/make` so we pass - // the options through environment variables that are fetched and understood by both. - // - // FIXME: the guard against msvc shouldn't need to be here - if target.is_msvc() { - if let Some(ref cl) = self.config.llvm_clang_cl { - cargo.env("CC", cl).env("CXX", cl); - } - } else { - let ccache = self.config.ccache.as_ref(); - let ccacheify = |s: &Path| { - let ccache = match ccache { - Some(ref s) => s, - None => return s.display().to_string(), - }; - // FIXME: the cc-rs crate only recognizes the literal strings - // `ccache` and `sccache` when doing caching compilations, so we - // mirror that here. It should probably be fixed upstream to - // accept a new env var or otherwise work with custom ccache - // vars. - match &ccache[..] { - "ccache" | "sccache" => format!("{} {}", ccache, s.display()), - _ => s.display().to_string(), - } - }; - let triple_underscored = target.triple.replace("-", "_"); - let cc = ccacheify(&self.cc(target)); - cargo.env(format!("CC_{triple_underscored}"), &cc); - - let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" "); - cargo.env(format!("CFLAGS_{triple_underscored}"), &cflags); - - if let Some(ar) = self.ar(target) { - let ranlib = format!("{} s", ar.display()); - cargo - .env(format!("AR_{triple_underscored}"), ar) - .env(format!("RANLIB_{triple_underscored}"), ranlib); - } - - if let Ok(cxx) = self.cxx(target) { - let cxx = ccacheify(&cxx); - let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" "); - cargo - .env(format!("CXX_{triple_underscored}"), &cxx) - .env(format!("CXXFLAGS_{triple_underscored}"), cxxflags); - } + if cmd != "check" { + self.configure_linker( + compiler, + target, + &mut cargo, + &mut rustflags, + &mut rustdocflags, + &mut hostflags, + ); } // If Control Flow Guard is enabled, pass the `control-flow-guard` flag to rustc @@ -2142,6 +2034,136 @@ impl<'a> Builder<'a> { Cargo { command: cargo, rustflags, rustdocflags, hostflags, allow_features } } + fn configure_linker( + &self, + compiler: Compiler, + target: TargetSelection, + cargo: &mut Command, + rustflags: &mut Rustflags, + rustdocflags: &mut Rustflags, + hostflags: &mut HostFlags, + ) { + // Dealing with rpath here is a little special, so let's go into some + // detail. First off, `-rpath` is a linker option on Unix platforms + // which adds to the runtime dynamic loader path when looking for + // dynamic libraries. We use this by default on Unix platforms to ensure + // that our nightlies behave the same on Windows, that is they work out + // of the box. This can be disabled by setting `rpath = false` in `[rust]` + // table of `config.toml` + // + // Ok, so the astute might be wondering "why isn't `-C rpath` used + // here?" and that is indeed a good question to ask. This codegen + // option is the compiler's current interface to generating an rpath. + // Unfortunately it doesn't quite suffice for us. The flag currently + // takes no value as an argument, so the compiler calculates what it + // should pass to the linker as `-rpath`. This unfortunately is based on + // the **compile time** directory structure which when building with + // Cargo will be very different than the runtime directory structure. + // + // All that's a really long winded way of saying that if we use + // `-Crpath` then the executables generated have the wrong rpath of + // something like `$ORIGIN/deps` when in fact the way we distribute + // rustc requires the rpath to be `$ORIGIN/../lib`. + // + // So, all in all, to set up the correct rpath we pass the linker + // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it + // fun to pass a flag to a tool to pass a flag to pass a flag to a tool + // to change a flag in a binary? + if self.config.rpath_enabled(target) && helpers::use_host_linker(target) { + let libdir = self.sysroot_libdir_relative(compiler).to_str().unwrap(); + let rpath = if target.contains("apple") { + // Note that we need to take one extra step on macOS to also pass + // `-Wl,-instal_name,@rpath/...` to get things to work right. To + // do that we pass a weird flag to the compiler to get it to do + // so. Note that this is definitely a hack, and we should likely + // flesh out rpath support more fully in the future. + rustflags.arg("-Zosx-rpath-install-name"); + Some(format!("-Wl,-rpath,@loader_path/../{libdir}")) + } else if !target.is_windows() && !target.contains("aix") && !target.contains("xous") { + rustflags.arg("-Clink-args=-Wl,-z,origin"); + Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}")) + } else { + None + }; + if let Some(rpath) = rpath { + rustflags.arg(&format!("-Clink-args={rpath}")); + } + } + + for arg in linker_args(self, compiler.host, LldThreads::Yes) { + hostflags.arg(&arg); + } + + if let Some(target_linker) = self.linker(target) { + let target = crate::envify(&target.triple); + cargo.env(&format!("CARGO_TARGET_{target}_LINKER"), target_linker); + } + // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not + // `linker_args` here. + for flag in linker_flags(self, target, LldThreads::Yes) { + rustflags.arg(&flag); + } + for arg in linker_args(self, target, LldThreads::Yes) { + rustdocflags.arg(&arg); + } + + if !self.config.dry_run() && self.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz") + { + rustflags.arg("-Clink-arg=-gz"); + } + + // Throughout the build Cargo can execute a number of build scripts + // compiling C/C++ code and we need to pass compilers, archivers, flags, etc + // obtained previously to those build scripts. + // Build scripts use either the `cc` crate or `configure/make` so we pass + // the options through environment variables that are fetched and understood by both. + // + // FIXME: the guard against msvc shouldn't need to be here + if target.is_msvc() { + if let Some(ref cl) = self.config.llvm_clang_cl { + cargo.env("CC", cl).env("CXX", cl); + } + } else { + let ccache = self.config.ccache.as_ref(); + let ccacheify = |s: &Path| { + let ccache = match ccache { + Some(ref s) => s, + None => return s.display().to_string(), + }; + // FIXME: the cc-rs crate only recognizes the literal strings + // `ccache` and `sccache` when doing caching compilations, so we + // mirror that here. It should probably be fixed upstream to + // accept a new env var or otherwise work with custom ccache + // vars. + match &ccache[..] { + "ccache" | "sccache" => format!("{} {}", ccache, s.display()), + _ => s.display().to_string(), + } + }; + let triple_underscored = target.triple.replace("-", "_"); + let cc = ccacheify(&self.cc(target)); + cargo.env(format!("CC_{triple_underscored}"), &cc); + + let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" "); + cargo.env(format!("CFLAGS_{triple_underscored}"), &cflags); + + if let Some(ar) = self.ar(target) { + let ranlib = format!("{} s", ar.display()); + cargo + .env(format!("AR_{triple_underscored}"), ar) + .env(format!("RANLIB_{triple_underscored}"), ranlib); + } + + if let Ok(cxx) = self.cxx(target) { + let cxx = ccacheify(&cxx); + let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" "); + cargo + .env(format!("CXX_{triple_underscored}"), &cxx) + .env(format!("CXXFLAGS_{triple_underscored}"), cxxflags); + } + } + } + /// Ensure that a given step is built, returning its output. This will /// cache the step, so it is safe (and good!) to call this as often as /// needed to ensure that all dependencies are built. diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8be4def15dedc..00ebd91f3871f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2467,6 +2467,8 @@ impl<'test> TestCx<'test> { "-Zvalidate-mir", "-Zlint-mir", "-Zdump-mir-exclude-pass-number", + "--crate-type=rlib", + "-Clink-dead-code", ]); if let Some(pass) = &self.props.mir_unit_test { rustc.args(&["-Zmir-opt-level=0", &format!("-Zmir-enable-passes=+{}", pass)]); diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff index 8f2baf4a3b61c..1be0a4f2d2976 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff @@ -4,35 +4,16 @@ fn g() -> () { let mut _0: (); let _1: (); -+ let mut _2: fn() {main}; -+ scope 1 (inlined f::) { -+ debug g => _2; -+ let mut _3: &fn() {main}; -+ let _4: (); -+ } bb0: { StorageLive(_1); -- _1 = f::(main) -> [return: bb1, unwind unreachable]; -+ StorageLive(_2); -+ _2 = main; -+ StorageLive(_4); -+ StorageLive(_3); -+ _3 = &_2; -+ _4 = >::call(move _3, const ()) -> [return: bb2, unwind unreachable]; + _1 = f::(main) -> [return: bb1, unwind unreachable]; } bb1: { -+ StorageDead(_4); -+ StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb2: { -+ StorageDead(_3); -+ drop(_2) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff index 1fd1014ba1d53..da516220d5048 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff @@ -4,43 +4,16 @@ fn g() -> () { let mut _0: (); let _1: (); -+ let mut _2: fn() {main}; -+ scope 1 (inlined f::) { -+ debug g => _2; -+ let mut _3: &fn() {main}; -+ let _4: (); -+ } bb0: { StorageLive(_1); -- _1 = f::(main) -> [return: bb1, unwind continue]; -+ StorageLive(_2); -+ _2 = main; -+ StorageLive(_4); -+ StorageLive(_3); -+ _3 = &_2; -+ _4 = >::call(move _3, const ()) -> [return: bb2, unwind: bb3]; + _1 = f::(main) -> [return: bb1, unwind continue]; } bb1: { -+ StorageDead(_4); -+ StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb2: { -+ StorageDead(_3); -+ drop(_2) -> [return: bb1, unwind continue]; -+ } -+ -+ bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; -+ } -+ -+ bb4 (cleanup): { -+ resume; } } diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs index 350724235ba04..c251226673d5f 100644 --- a/tests/mir-opt/inline/cycle.rs +++ b/tests/mir-opt/inline/cycle.rs @@ -13,9 +13,7 @@ fn f(g: impl Fn()) { #[inline(always)] fn g() { // CHECK-LABEL: fn g( - // CHECK-NOT: inlined - // CHECK: (inlined f::) - // CHECK-NOT: inlined + // CHECK-NOT: (inlined f::) f(main); } diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff index d437dbf5763a2..142b9c5659889 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff @@ -7,6 +7,10 @@ + scope 1 (inlined ::call) { + scope 2 (inlined as Call>::call) { + scope 3 (inlined ::call) { ++ scope 4 (inlined as Call>::call) { ++ scope 5 (inlined ::call) { ++ } ++ } + } + } + } @@ -14,7 +18,7 @@ bb0: { StorageLive(_1); - _1 = ::call() -> [return: bb1, unwind unreachable]; -+ _1 = as Call>::call() -> [return: bb1, unwind unreachable]; ++ _1 = as Call>::call() -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff index 8314526ee0431..193ada05f0234 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff @@ -7,6 +7,10 @@ + scope 1 (inlined ::call) { + scope 2 (inlined as Call>::call) { + scope 3 (inlined ::call) { ++ scope 4 (inlined as Call>::call) { ++ scope 5 (inlined ::call) { ++ } ++ } + } + } + } @@ -14,7 +18,7 @@ bb0: { StorageLive(_1); - _1 = ::call() -> [return: bb1, unwind continue]; -+ _1 = as Call>::call() -> [return: bb1, unwind continue]; ++ _1 = as Call>::call() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index ffb1aedd2ea90..a10061ed9412c 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index ffb1aedd2ea90..a10061ed9412c 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); From 2116ed723d178313cac1ff829d5a7417bba1cd3b Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 30 Jan 2024 22:28:28 -0500 Subject: [PATCH 610/676] Tweak a few mir-opt tests instead of using -Clink-dead-code --- src/bootstrap/src/core/build_steps/test.rs | 1 - src/tools/compiletest/src/runtest.rs | 1 - tests/mir-opt/fn_ptr_shim.rs | 2 +- tests/mir-opt/retag.rs | 2 +- tests/mir-opt/slice_drop_shim.rs | 6 ++++-- tests/mir-opt/unusual_item_types.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index e1a1c416ae993..baf1b5a4a1afd 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1470,7 +1470,6 @@ impl Step for MirOpt { }; if builder.config.cmd.bless() { - crate::utils::cc_detect::find_target(builder, self.compiler.host); // All that we really need to do is cover all combinations of 32/64-bit and unwind/abort, // but while we're at it we might as well flex our cross-compilation support. This // selection covers all our tier 1 operating systems and architectures using only tier diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 00ebd91f3871f..ed1c559e1f692 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2468,7 +2468,6 @@ impl<'test> TestCx<'test> { "-Zlint-mir", "-Zdump-mir-exclude-pass-number", "--crate-type=rlib", - "-Clink-dead-code", ]); if let Some(pass) = &self.props.mir_unit_test { rustc.args(&["-Zmir-opt-level=0", &format!("-Zmir-enable-passes=+{}", pass)]); diff --git a/tests/mir-opt/fn_ptr_shim.rs b/tests/mir-opt/fn_ptr_shim.rs index c82260baefee3..2650cbf9704f3 100644 --- a/tests/mir-opt/fn_ptr_shim.rs +++ b/tests/mir-opt/fn_ptr_shim.rs @@ -5,7 +5,7 @@ // (as only `FnDef` and `FnPtr` callees are allowed in MIR). // EMIT_MIR core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir -fn main() { +pub fn main() { call(noop as fn()); } diff --git a/tests/mir-opt/retag.rs b/tests/mir-opt/retag.rs index 1e4b017dad5fa..554b8ece90f28 100644 --- a/tests/mir-opt/retag.rs +++ b/tests/mir-opt/retag.rs @@ -28,7 +28,7 @@ impl Drop for Test { // EMIT_MIR retag.main.SimplifyCfg-elaborate-drops.after.mir // EMIT_MIR retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir -fn main() { +pub fn main() { let mut x = 0; { let v = Test(0).foo(&mut x); // just making sure we do not panic when there is a tuple struct ctor diff --git a/tests/mir-opt/slice_drop_shim.rs b/tests/mir-opt/slice_drop_shim.rs index cac0a349128c3..037e048b3b797 100644 --- a/tests/mir-opt/slice_drop_shim.rs +++ b/tests/mir-opt/slice_drop_shim.rs @@ -1,6 +1,8 @@ // skip-filecheck -// compile-flags: -Zmir-opt-level=0 - +// compile-flags: -Zmir-opt-level=0 -Clink-dead-code +// mir-opt tests are always built as rlibs so that they seamlessly cross-compile, +// so this test only produces MIR for the drop_in_place we're looking for +// if we use -Clink-dead-code. // EMIT_MIR core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir fn main() { diff --git a/tests/mir-opt/unusual_item_types.rs b/tests/mir-opt/unusual_item_types.rs index 49b663b4f8298..fa6ba515473ba 100644 --- a/tests/mir-opt/unusual_item_types.rs +++ b/tests/mir-opt/unusual_item_types.rs @@ -23,7 +23,7 @@ enum E { V = 5, } -fn main() { +pub fn main() { let f = Test::X as fn(usize) -> Test; // EMIT_MIR core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir let v = Vec::::new(); From 476f91cbf7fd4080fea7ede8c145c83f0b589ff9 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 5 Feb 2024 19:52:02 -0500 Subject: [PATCH 611/676] Don't call std_cargo to build mir-only sysroots --- src/bootstrap/src/core/build_steps/compile.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 3c0d074807d39..73f29d6bb6f45 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -239,7 +239,7 @@ impl Step for Std { let mut cargo = if self.is_for_mir_opt_tests { let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "check"); cargo.rustflag("-Zalways-encode-mir"); - std_cargo(builder, target, compiler.stage, &mut cargo); + cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml")); cargo } else { let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build"); From 3c7a8b9d7168b0e59f4264a987ffea54b54f0223 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 6 Feb 2024 23:40:58 -0500 Subject: [PATCH 612/676] Fixup async_closure_shims mir-opt test --- tests/mir-opt/async_closure_shims.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs index ef3bdaaa145a3..2c99a2dad37a7 100644 --- a/tests/mir-opt/async_closure_shims.rs +++ b/tests/mir-opt/async_closure_shims.rs @@ -33,7 +33,7 @@ async fn call_once(f: impl AsyncFnOnce(i32)) { // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.mir -fn main() { +pub fn main() { block_on(async { let b = 2i32; let mut async_closure = async move |a: i32| { From 363b098245c44401dda0040c80624187539c3141 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 20 Jan 2024 15:21:27 +0300 Subject: [PATCH 613/676] hir: Make sure all `HirId`s have corresponding HIR `Node`s --- compiler/rustc_ast_lowering/src/index.rs | 42 ++++++++++++++++--- compiler/rustc_ast_lowering/src/lib.rs | 3 +- .../src/diagnostics/region_errors.rs | 3 +- compiler/rustc_hir/src/hir.rs | 33 ++++++++------- .../rustc_hir_analysis/src/collect/type_of.rs | 2 + compiler/rustc_hir_pretty/src/lib.rs | 7 ++++ .../src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 10 +---- compiler/rustc_middle/src/hir/map/mod.rs | 12 ++++-- .../clippy_lints/src/min_ident_chars.rs | 2 +- 10 files changed, 79 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 993ddf00eb5b9..ff3870cf11b92 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -15,7 +15,7 @@ struct NodeCollector<'a, 'hir> { bodies: &'a SortedMap>, /// Outputs - nodes: IndexVec>>, + nodes: IndexVec>, parenting: LocalDefIdMap, /// The parent of this node @@ -29,16 +29,19 @@ pub(super) fn index_hir<'hir>( tcx: TyCtxt<'hir>, item: hir::OwnerNode<'hir>, bodies: &SortedMap>, -) -> (IndexVec>>, LocalDefIdMap) { - let mut nodes = IndexVec::new(); + num_nodes: usize, +) -> (IndexVec>, LocalDefIdMap) { + let zero_id = ItemLocalId::new(0); + let err_node = ParentedNode { parent: zero_id, node: Node::Err(item.span()) }; + let mut nodes = IndexVec::from_elem_n(err_node, num_nodes); // This node's parent should never be accessed: the owner's parent is computed by the // hir_owner_parent query. Make it invalid (= ItemLocalId::MAX) to force an ICE whenever it is // used. - nodes.push(Some(ParentedNode { parent: ItemLocalId::INVALID, node: item.into() })); + nodes[zero_id] = ParentedNode { parent: ItemLocalId::INVALID, node: item.into() }; let mut collector = NodeCollector { tcx, owner: item.def_id(), - parent_node: ItemLocalId::new(0), + parent_node: zero_id, nodes, bodies, parenting: Default::default(), @@ -54,6 +57,14 @@ pub(super) fn index_hir<'hir>( OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item), }; + for (local_id, node) in collector.nodes.iter_enumerated() { + if let Node::Err(span) = node.node { + let hir_id = HirId { owner: item.def_id(), local_id }; + let msg = format!("ID {hir_id} not encountered when visiting item HIR"); + tcx.dcx().span_delayed_bug(*span, msg); + } + } + (collector.nodes, collector.parenting) } @@ -88,7 +99,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } } - self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node }); + self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node }; } fn with_parent(&mut self, parent_node_id: HirId, f: F) { @@ -348,4 +359,23 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.visit_nested_foreign_item(id); } + + fn visit_where_predicate(&mut self, predicate: &'hir WherePredicate<'hir>) { + match predicate { + WherePredicate::BoundPredicate(pred) => { + self.insert(pred.span, pred.hir_id, Node::WhereBoundPredicate(pred)); + self.with_parent(pred.hir_id, |this| { + intravisit::walk_where_predicate(this, predicate) + }) + } + _ => intravisit::walk_where_predicate(self, predicate), + } + } + + fn visit_array_length(&mut self, len: &'hir ArrayLen) { + match len { + ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)), + ArrayLen::Body(..) => intravisit::walk_array_len(self, len), + } + } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 063b6627050bc..3f3826270765a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -675,7 +675,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { (None, None) }; - let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies); + let num_nodes = self.item_local_id_counter.as_usize(); + let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes); let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies }; let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash }; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8c8ca1ead400b..0733fc48ed56c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -216,7 +216,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(id) = placeholder.bound.kind.get_id() && let Some(placeholder_id) = id.as_local() && let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id) - && let Some(generics_impl) = hir.get_parent(gat_hir_id).generics() + && let Some(generics_impl) = + hir.get_parent(hir.parent_id(gat_hir_id)).generics() { Some((gat_hir_id, generics_impl)) } else { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ff50086ff8f98..2468e91e8b945 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -835,7 +835,7 @@ pub struct OwnerNodes<'tcx> { // The zeroth node's parent should never be accessed: the owner's parent is computed by the // hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally // used. - pub nodes: IndexVec>>, + pub nodes: IndexVec>, /// Content of local bodies. pub bodies: SortedMap>, } @@ -843,9 +843,8 @@ pub struct OwnerNodes<'tcx> { impl<'tcx> OwnerNodes<'tcx> { pub fn node(&self) -> OwnerNode<'tcx> { use rustc_index::Idx; - let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; - let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. - node + // Indexing must ensure it is an OwnerNode. + self.nodes[ItemLocalId::new(0)].node.as_owner().unwrap() } } @@ -860,9 +859,7 @@ impl fmt::Debug for OwnerNodes<'_> { .nodes .iter_enumerated() .map(|(id, parented_node)| { - let parented_node = parented_node.as_ref().map(|node| node.parent); - - debug_fn(move |f| write!(f, "({id:?}, {parented_node:?})")) + debug_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent)) }) .collect::>(), ) @@ -3351,13 +3348,15 @@ impl<'hir> OwnerNode<'hir> { } } - pub fn span(&self) -> Span { + // Span by reference to pass to `Node::Err`. + #[allow(rustc::pass_by_value)] + pub fn span(&self) -> &'hir Span { match self { OwnerNode::Item(Item { span, .. }) | OwnerNode::ForeignItem(ForeignItem { span, .. }) | OwnerNode::ImplItem(ImplItem { span, .. }) - | OwnerNode::TraitItem(TraitItem { span, .. }) => *span, - OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span, + | OwnerNode::TraitItem(TraitItem { span, .. }) => span, + OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span, } } @@ -3486,17 +3485,18 @@ pub enum Node<'hir> { Arm(&'hir Arm<'hir>), Block(&'hir Block<'hir>), Local(&'hir Local<'hir>), - /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants /// with synthesized constructors. Ctor(&'hir VariantData<'hir>), - Lifetime(&'hir Lifetime), GenericParam(&'hir GenericParam<'hir>), - Crate(&'hir Mod<'hir>), - Infer(&'hir InferArg), + WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>), + ArrayLenInfer(&'hir InferArg), + // Span by reference to minimize `Node`'s size + #[allow(rustc::pass_by_value)] + Err(&'hir Span), } impl<'hir> Node<'hir> { @@ -3541,7 +3541,10 @@ impl<'hir> Node<'hir> { | Node::Crate(..) | Node::Ty(..) | Node::TraitRef(..) - | Node::Infer(..) => None, + | Node::Infer(..) + | Node::WhereBoundPredicate(..) + | Node::ArrayLenInfer(..) + | Node::Err(..) => None, } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 5cdcc1bb860b2..2b73cbc0e4666 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -509,6 +509,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder bug!("unexpected non-type Node::GenericParam: {:?}", x), }, + Node::ArrayLenInfer(_) => tcx.types.usize, + x => { bug!("unexpected sort of node in type_of(): {:?}", x); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9d0c5cb0f32b0..95f8a754664b7 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -117,6 +117,13 @@ impl<'a> State<'a> { Node::Ctor(..) => panic!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), + Node::WhereBoundPredicate(pred) => { + self.print_formal_generic_params(pred.bound_generic_params); + self.print_type(pred.bounded_ty); + self.print_bounds(":", pred.bounds); + } + Node::ArrayLenInfer(_) => self.word("_"), + Node::Err(_) => self.word("/*ERROR*/"), } } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5395ffda1d134..eccfd0d0c9654 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1055,7 +1055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.can_coerce(found, ty) { if let Some(node) = self.tcx.opt_hir_node(fn_id) && let Some(owner_node) = node.as_owner() - && let Some(span) = expr.span.find_ancestor_inside(owner_node.span()) + && let Some(span) = expr.span.find_ancestor_inside(*owner_node.span()) { err.multipart_suggestion( "you might have meant to return this value", diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 85631bd8edbfa..79aa9a547f7c6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1388,13 +1388,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if should_encode_fn_sig(def_kind) { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } - // FIXME: Some anonymous constants produced by `#[rustc_legacy_const_generics]` - // do not have corresponding HIR nodes, so some queries usually making sense for - // anonymous constants will not work on them and panic. It's not clear whether it - // can cause any observable issues or not. - let anon_const_without_hir = def_kind == DefKind::AnonConst - && tcx.opt_hir_node(tcx.local_def_id_to_hir_id(local_id)).is_none(); - if should_encode_generics(def_kind) && !anon_const_without_hir { + if should_encode_generics(def_kind) { let g = tcx.generics_of(def_id); record!(self.tables.generics_of[def_id] <- g); record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id)); @@ -1408,7 +1402,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } } - if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir { + if should_encode_type(tcx, local_id, def_kind) { record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); } if should_encode_constness(def_kind) { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index ba1ae46626b22..64e19e0946fd0 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -159,9 +159,7 @@ impl<'tcx> TyCtxt<'tcx> { /// 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); - let node = owner.nodes[id.local_id].as_ref()?; - Some(node.node) + Some(self.hir_owner_nodes(id.owner).nodes[id.local_id].node) } /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. @@ -233,7 +231,7 @@ impl<'hir> Map<'hir> { Some(self.tcx.hir_owner_parent(id.owner)) } else { let owner = self.tcx.hir_owner_nodes(id.owner); - let node = owner.nodes[id.local_id].as_ref()?; + let node = &owner.nodes[id.local_id]; let hir_id = HirId { owner: id.owner, local_id: node.parent }; // HIR indexing should have checked that. debug_assert_ne!(id.local_id, node.parent); @@ -994,6 +992,9 @@ impl<'hir> Map<'hir> { Node::Infer(i) => i.span, Node::Local(local) => local.span, Node::Crate(item) => item.spans.inner_span, + Node::WhereBoundPredicate(pred) => pred.span, + Node::ArrayLenInfer(inf) => inf.span, + Node::Err(span) => *span, } } @@ -1255,6 +1256,9 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { format!("{id} (generic_param {})", path_str(param.def_id)) } Some(Node::Crate(..)) => String::from("(root_crate)"), + Some(Node::WhereBoundPredicate(_)) => node_str("where bound predicate"), + Some(Node::ArrayLenInfer(_)) => node_str("array len infer"), + Some(Node::Err(_)) => node_str("error"), None => format!("{id} (unknown node)"), } } 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 41168230752a8..2f9f04832a750 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -94,7 +94,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { cx.tcx.opt_hir_node(hir_id) } else { let owner = cx.tcx.hir_owner_nodes(hir_id.owner); - owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node) + owner.nodes.get(hir_id.local_id).copied().map(|p| p.node) }; let Some(node) = node else { return; From a61019b29021b7635113b48e470dbac724c81c76 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 21 Jan 2024 21:13:15 +0300 Subject: [PATCH 614/676] hir: Remove `fn opt_hir_id` and `fn opt_span` --- .../src/diagnostics/conflict_errors.rs | 121 ++++++++--------- .../src/diagnostics/explain_borrow.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 14 +- compiler/rustc_hir/src/intravisit.rs | 6 +- .../rustc_hir_analysis/src/check/entry.rs | 14 +- .../wrong_number_of_generic_args.rs | 3 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 4 +- compiler/rustc_hir_typeck/src/demand.rs | 49 +++---- compiler/rustc_hir_typeck/src/expr.rs | 5 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 74 +++++----- .../rustc_hir_typeck/src/method/suggest.rs | 6 +- .../rustc_hir_typeck/src/rvalue_scopes.rs | 4 +- compiler/rustc_hir_typeck/src/upvar.rs | 4 +- .../src/infer/error_reporting/mod.rs | 2 +- .../rustc_infer/src/infer/opaque_types.rs | 2 +- .../src/traits/error_reporting/mod.rs | 3 +- compiler/rustc_middle/src/hir/map/mod.rs | 126 ++++++++---------- compiler/rustc_middle/src/hir/mod.rs | 7 +- compiler/rustc_passes/src/check_attr.rs | 13 +- compiler/rustc_passes/src/loops.rs | 4 +- .../src/traits/error_reporting/suggestions.rs | 43 +++--- .../error_reporting/type_err_ctxt_ext.rs | 12 +- src/librustdoc/html/render/span_map.rs | 4 +- .../clippy/clippy_lints/src/absolute_paths.rs | 2 +- .../src/casts/cast_slice_different_sizes.rs | 5 +- .../src/casts/unnecessary_cast.rs | 3 +- .../clippy_lints/src/derivable_impls.rs | 2 +- .../clippy/clippy_lints/src/empty_drop.rs | 2 +- src/tools/clippy/clippy_lints/src/escape.rs | 6 +- .../clippy/clippy_lints/src/explicit_write.rs | 2 +- .../clippy_lints/src/index_refutable_slice.rs | 4 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 6 +- .../clippy_lints/src/loops/same_item_push.rs | 2 +- .../clippy_lints/src/manual_rem_euclid.rs | 2 +- .../clippy_lints/src/methods/filter_next.rs | 2 +- .../src/methods/option_map_unwrap_or.rs | 4 +- .../clippy_lints/src/min_ident_chars.rs | 2 +- .../src/mixed_read_write_in_expression.rs | 5 +- .../clippy/clippy_lints/src/non_copy_const.rs | 2 +- .../clippy_lints/src/same_name_method.rs | 4 +- .../src/self_named_constructors.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 10 +- 44 files changed, 267 insertions(+), 326 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6debb3362b04c..64efc8b7ee356 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -401,66 +401,60 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let typeck = self.infcx.tcx.typeck(self.mir_def_id()); let hir_id = hir.parent_id(expr.hir_id); - if let Some(parent) = self.infcx.tcx.opt_hir_node(hir_id) { - let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind - && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id) - { - (def_id.as_local(), args, 1) - } else if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::Call(call, args) = parent_expr.kind - && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind() - { - (def_id.as_local(), args, 0) - } else { - (None, &[][..], 0) + let parent = self.infcx.tcx.hir_node(hir_id); + let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind + && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id) + { + (def_id.as_local(), args, 1) + } else if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call, args) = parent_expr.kind + && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind() + { + (def_id.as_local(), args, 0) + } else { + (None, &[][..], 0) + }; + if let Some(def_id) = def_id + && let node = + self.infcx.tcx.hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id)) + && let Some(fn_sig) = node.fn_sig() + && let Some(ident) = node.ident() + && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) + && let Some(arg) = fn_sig.decl.inputs.get(pos + offset) + { + let mut span: MultiSpan = arg.span.into(); + span.push_span_label( + arg.span, + "this parameter takes ownership of the value".to_string(), + ); + let descr = match node.fn_kind() { + Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function", + Some(hir::intravisit::FnKind::Method(..)) => "method", + Some(hir::intravisit::FnKind::Closure) => "closure", }; - if let Some(def_id) = def_id - && let Some(node) = self - .infcx - .tcx - .opt_hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id)) - && let Some(fn_sig) = node.fn_sig() - && let Some(ident) = node.ident() - && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) - && let Some(arg) = fn_sig.decl.inputs.get(pos + offset) - { - let mut span: MultiSpan = arg.span.into(); - span.push_span_label( - arg.span, - "this parameter takes ownership of the value".to_string(), - ); - let descr = match node.fn_kind() { - Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function", - Some(hir::intravisit::FnKind::Method(..)) => "method", - Some(hir::intravisit::FnKind::Closure) => "closure", - }; - span.push_span_label(ident.span, format!("in this {descr}")); - err.span_note( - span, - format!( - "consider changing this parameter type in {descr} `{ident}` to \ + span.push_span_label(ident.span, format!("in this {descr}")); + err.span_note( + span, + format!( + "consider changing this parameter type in {descr} `{ident}` to \ borrow instead if owning the value isn't necessary", - ), - ); - } - let place = &self.move_data.move_paths[mpi].place; - let ty = place.ty(self.body, self.infcx.tcx).ty; - if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind - && let hir::ExprKind::Path(hir::QPath::LangItem( - LangItem::IntoIterIntoIter, - _, - )) = call_expr.kind - { - // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. - } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = - move_spans - { - // We already suggest cloning for these cases in `explain_captures`. - } else { - self.suggest_cloning(err, ty, expr, move_span); - } + ), + ); + } + let place = &self.move_data.move_paths[mpi].place; + let ty = place.ty(self.body, self.infcx.tcx).ty; + if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind + && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) = + call_expr.kind + { + // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. + } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans + { + // We already suggest cloning for these cases in `explain_captures`. + } else { + self.suggest_cloning(err, ty, expr, move_span); } } if let Some(pat) = finder.pat { @@ -1762,7 +1756,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn_decl: hir::FnDecl { inputs, .. }, .. }) = e.kind - && let Some(hir::Node::Expr(body)) = self.tcx.opt_hir_node(body.hir_id) + && let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id) { self.suggest_arg = "this: &Self".to_string(); if inputs.len() > 0 { @@ -1828,11 +1822,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - if let Some(hir::Node::ImplItem(hir::ImplItem { + if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(_fn_sig, body_id), .. - })) = self.infcx.tcx.opt_hir_node(self.mir_hir_id()) - && let Some(hir::Node::Expr(expr)) = self.infcx.tcx.opt_hir_node(body_id.hir_id) + }) = self.infcx.tcx.hir_node(self.mir_hir_id()) + && let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id) { let mut finder = ExpressionFinder { capture_span: *capture_kind_span, @@ -2400,8 +2394,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let proper_span = proper_span.source_callsite(); if let Some(scope) = self.body.source_scopes.get(source_info.scope) && let ClearCrossCrate::Set(scope_data) = &scope.local_data - && let Some(node) = self.infcx.tcx.opt_hir_node(scope_data.lint_root) - && let Some(id) = node.body_id() + && let Some(id) = self.infcx.tcx.hir_node(scope_data.lint_root).body_id() && let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind { for stmt in block.stmts { diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 4f66468a865f8..716d30c5a485d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -87,7 +87,7 @@ impl<'tcx> BorrowExplanation<'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind && let [hir::PathSegment { ident, args: None, .. }] = p.segments && let hir::def::Res::Local(hir_id) = p.res - && let Some(hir::Node::Pat(pat)) = tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(pat) = tcx.hir_node(hir_id) { err.span_label(pat.span, format!("binding `{ident}` declared here")); } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 55649ec2f1645..ded282e4b4a28 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -396,7 +396,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar_hir_id = captured_place.get_root_variable(); - if let Some(Node::Pat(pat)) = self.infcx.tcx.opt_hir_node(upvar_hir_id) + if let Node::Pat(pat) = self.infcx.tcx.hir_node(upvar_hir_id) && let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, upvar_ident, _) = pat.kind { @@ -688,15 +688,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { break; } f_in_trait_opt.and_then(|f_in_trait| { - match self.infcx.tcx.opt_hir_node(f_in_trait) { - Some(Node::TraitItem(hir::TraitItem { + match self.infcx.tcx.hir_node(f_in_trait) { + Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn( hir::FnSig { decl: hir::FnDecl { inputs, .. }, .. }, _, ), .. - })) => { + }) => { let hir::Ty { span, .. } = inputs[local.index() - 1]; Some(span) } @@ -759,10 +759,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // // `let &b = a;` -> `let &(mut b) = a;` if let Some(hir_id) = hir_id - && let Some(hir::Node::Local(hir::Local { + && let hir::Node::Local(hir::Local { pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. }, .. - })) = self.infcx.tcx.opt_hir_node(hir_id) + }) = self.infcx.tcx.hir_node(hir_id) && let Ok(name) = self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span) { @@ -1206,7 +1206,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(hir_id) = hir_id - && let Some(hir::Node::Local(local)) = self.infcx.tcx.opt_hir_node(hir_id) + && let hir::Node::Local(local) = self.infcx.tcx.hir_node(hir_id) { let tables = self.infcx.tcx.typeck(def_id.as_local().unwrap()); if let Some(clone_trait) = self.infcx.tcx.lang_items().clone_trait() diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 27c834d848fc4..574b372be2ba5 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -108,8 +108,8 @@ impl<'a> FnKind<'a> { /// An abstract representation of the HIR `rustc_middle::hir::map::Map`. pub trait Map<'hir> { - /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. - fn find(&self, hir_id: HirId) -> Option>; + /// Retrieves the `Node` corresponding to `id`. + fn hir_node(&self, hir_id: HirId) -> Node<'hir>; fn body(&self, id: BodyId) -> &'hir Body<'hir>; fn item(&self, id: ItemId) -> &'hir Item<'hir>; fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>; @@ -119,7 +119,7 @@ pub trait Map<'hir> { // Used when no map is actually available, forcing manual implementation of nested visitors. impl<'hir> Map<'hir> for ! { - fn find(&self, _: HirId) -> Option> { + fn hir_node(&self, _: HirId) -> Node<'hir> { *self; } fn body(&self, _: BodyId) -> &'hir Body<'hir> { diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 649ac6c5aebbf..3d803258c8e5e 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -43,8 +43,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => { generics.params.is_empty().not().then_some(generics.span) } _ => { @@ -58,8 +58,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => { Some(generics.where_clause_span) } _ => { @@ -80,8 +80,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. }) => { Some(fn_sig.decl.output.span()) } _ => { @@ -202,7 +202,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { let start_t = tcx.type_of(start_def_id).instantiate_identity(); match start_t.kind() { ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.opt_hir_node(start_id) { + if let Node::Item(it) = tcx.hir_node(start_id) { if let hir::ItemKind::Fn(sig, generics, _) = &it.kind { let mut error = false; if !generics.params.is_empty() { diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 501915d2e7e53..3b1ee2975fd97 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -771,8 +771,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ); if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id) - && let Some(parent_node) = self.tcx.opt_hir_node(parent_node) - && let hir::Node::Expr(expr) = parent_node + && let hir::Node::Expr(expr) = self.tcx.hir_node(parent_node) { match &expr.kind { hir::ExprKind::Path(qpath) => self diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 95f8a754664b7..32d91b596b0bd 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -23,7 +23,7 @@ use std::cell::Cell; use std::vec; pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String { - to_string(&map, |s| s.print_node(map.find(hir_id).unwrap())) + to_string(&map, |s| s.print_node(map.hir_node(hir_id))) } pub enum AnnNode<'a> { diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ca636ebcade04..2beabc0835db1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1715,8 +1715,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let ret_msg = "return a value for the case when the loop has zero elements to iterate on"; let ret_ty_msg = "otherwise consider changing the return type to account for that possibility"; - if let Some(node) = tcx.opt_hir_node(item.into()) - && let Some(body_id) = node.body_id() + let node = tcx.hir_node(item.into()); + if let Some(body_id) = node.body_id() && let Some(sig) = node.fn_sig() && let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind && !ty.is_never() diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index b6dfc34d3ac19..d8974251de040 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -561,11 +561,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut parent; 'outer: loop { // Climb the HIR tree to see if the current `Expr` is part of a `break;` statement. - let Some( - hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. }) - | hir::Node::Block(hir::Block { expr: Some(&ref p), .. }) - | hir::Node::Expr(&ref p), - ) = self.tcx.opt_hir_node(parent_id) + let (hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. }) + | hir::Node::Block(hir::Block { expr: Some(&ref p), .. }) + | hir::Node::Expr(&ref p)) = self.tcx.hir_node(parent_id) else { break; }; @@ -578,20 +576,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut direct = false; loop { // Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to. - let parent = match self.tcx.opt_hir_node(parent_id) { - Some(hir::Node::Expr(&ref parent)) => { + let parent = match self.tcx.hir_node(parent_id) { + hir::Node::Expr(&ref parent) => { parent_id = self.tcx.hir().parent_id(parent.hir_id); parent } - Some(hir::Node::Stmt(hir::Stmt { + hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Semi(&ref parent) | hir::StmtKind::Expr(&ref parent), .. - })) => { + }) => { parent_id = self.tcx.hir().parent_id(*hir_id); parent } - Some(hir::Node::Block(_)) => { + hir::Node::Block(_) => { parent_id = self.tcx.hir().parent_id(parent_id); parent } @@ -680,17 +678,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: Option>, ) { let parent = self.tcx.hir().parent_id(expr.hir_id); - match (self.tcx.opt_hir_node(parent), error) { - (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _) + match (self.tcx.hir_node(parent), error) { + (hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. }), _) if init.hir_id == expr.hir_id => { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); } ( - Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Assign(lhs, rhs, _), .. - })), + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }), Some(TypeError::Sorts(ExpectedFound { expected, .. })), ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => { // We ignore closures explicitly because we already point at them elsewhere. @@ -725,7 +721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) => { - if let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) { + if let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id) { primary_span = pat.span; secondary_span = pat.span; match self.tcx.hir().find_parent(pat.hir_id) { @@ -774,9 +770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } ( - Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Binary(_, lhs, rhs), .. - })), + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(_, lhs, rhs), .. }), Some(TypeError::Sorts(ExpectedFound { expected, .. })), ) if rhs.hir_id == expr.hir_id && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected) => @@ -797,8 +791,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else { return; }; - let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. })) = - self.tcx.opt_hir_node(parent) + let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) = + self.tcx.hir_node(parent) else { return; }; @@ -1022,13 +1016,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Path { res: hir::def::Res::Local(bind_hir_id), .. }, )) = expr.kind { - let bind = self.tcx.opt_hir_node(*bind_hir_id); - let parent = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*bind_hir_id)); - if let Some(hir::Node::Pat(hir::Pat { - kind: hir::PatKind::Binding(_, _hir_id, _, _), - .. - })) = bind - && let Some(hir::Node::Pat(hir::Pat { default_binding_modes: false, .. })) = parent + let bind = self.tcx.hir_node(*bind_hir_id); + let parent = self.tcx.hir_node(self.tcx.hir().parent_id(*bind_hir_id)); + if let hir::Node::Pat(hir::Pat { + kind: hir::PatKind::Binding(_, _hir_id, _, _), .. + }) = bind + && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent { return true; } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1adde8c21b8e2..400c8673d919e 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1017,7 +1017,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { then: impl FnOnce(&hir::Expr<'_>), ) { let mut parent = self.tcx.hir().parent_id(original_expr_id); - while let Some(node) = self.tcx.opt_hir_node(parent) { + loop { + let node = self.tcx.hir_node(parent); match node { hir::Node::Expr(hir::Expr { kind: @@ -1471,8 +1472,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let hir::TyKind::Array(_, length) = ty.peel_refs().kind && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length - && let Some(span) = self.tcx.hir().opt_span(hir_id) { + let span = self.tcx.hir().span(hir_id); match self.dcx().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) { Some(mut err) => { err.span_suggestion( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d30c7a4fb3899..35b3f27d79127 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2060,7 +2060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let node = self .tcx .opt_local_def_id_to_hir_id(self.tcx.hir().get_parent_item(call_expr.hir_id)) - .and_then(|hir_id| self.tcx.opt_hir_node(hir_id)); + .map(|hir_id| self.tcx.hir_node(hir_id)); match node { Some(hir::Node::Item(item)) => call_finder.visit_item(item), Some(hir::Node::TraitItem(item)) => call_finder.visit_trait_item(item), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index eccfd0d0c9654..ed0bdb9bdaa0d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -682,8 +682,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is and we were expecting a Box, ergo Pin>, we // can suggest Box::pin. let parent = self.tcx.hir().parent_id(expr.hir_id); - let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) = - self.tcx.opt_hir_node(parent) + let Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. }) = + self.tcx.hir_node(parent) else { return false; }; @@ -908,9 +908,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::Param(expected_ty_as_param) = expected.kind() else { return }; - let fn_node = self.tcx.opt_hir_node(fn_id); + let fn_node = self.tcx.hir_node(fn_id); - let Some(hir::Node::Item(hir::Item { + let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn( hir::FnSig { @@ -921,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _body_id, ), .. - })) = fn_node + }) = fn_node else { return; }; @@ -1053,8 +1053,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let ty = self.normalize(expr.span, ty); if self.can_coerce(found, ty) { - if let Some(node) = self.tcx.opt_hir_node(fn_id) - && let Some(owner_node) = node.as_owner() + if let Some(owner_node) = self.tcx.hir_node(fn_id).as_owner() && let Some(span) = expr.span.find_ancestor_inside(*owner_node.span()) { err.multipart_suggestion( @@ -1684,15 +1683,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, hir::Path { segments: [_], res: crate::Res::Local(binding), .. }, )) => { - let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.opt_hir_node(*binding) - else { - return expr; - }; - let Some(parent) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) else { + let hir::Node::Pat(hir::Pat { hir_id, .. }) = self.tcx.hir_node(*binding) else { return expr; }; - match parent { + match self.tcx.hir_node(self.tcx.hir().parent_id(*hir_id)) { // foo.clone() hir::Node::Local(hir::Local { init: Some(init), .. }) => { self.note_type_is_not_clone_inner_expr(init) @@ -1703,8 +1698,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: hir::PatKind::Tuple(pats, ..), .. }) => { - let Some(hir::Node::Local(hir::Local { init: Some(init), .. })) = - self.tcx.opt_hir_node(self.tcx.hir().parent_id(*pat_hir_id)) + let hir::Node::Local(hir::Local { init: Some(init), .. }) = + self.tcx.hir_node(self.tcx.hir().parent_id(*pat_hir_id)) else { return expr; }; @@ -1736,10 +1731,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr_kind && let hir::Path { segments: [_], res: crate::Res::Local(binding), .. } = call_expr_path - && let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = - self.tcx.opt_hir_node(*binding) - && let Some(closure) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) - && let hir::Node::Local(hir::Local { init: Some(init), .. }) = closure + && let hir::Node::Pat(hir::Pat { hir_id, .. }) = self.tcx.hir_node(*binding) + && let hir::Node::Local(hir::Local { init: Some(init), .. }) = + self.tcx.hir_node(self.tcx.hir().parent_id(*hir_id)) && let Expr { kind: hir::ExprKind::Closure(hir::Closure { body: body_id, .. }), .. @@ -1979,20 +1973,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unroll desugaring, to make sure this works for `for` loops etc. loop { parent = self.tcx.hir().parent_id(id); - if let Some(parent_span) = self.tcx.hir().opt_span(parent) { - if parent_span.find_ancestor_inside(expr.span).is_some() { - // The parent node is part of the same span, so is the result of the - // same expansion/desugaring and not the 'real' parent node. - id = parent; - continue; - } + let parent_span = self.tcx.hir().span(parent); + if parent_span.find_ancestor_inside(expr.span).is_some() { + // The parent node is part of the same span, so is the result of the + // same expansion/desugaring and not the 'real' parent node. + id = parent; + continue; } break; } - if let Some(hir::Node::Block(&hir::Block { - span: block_span, expr: Some(e), .. - })) = self.tcx.opt_hir_node(parent) + if let hir::Node::Block(&hir::Block { span: block_span, expr: Some(e), .. }) = + self.tcx.hir_node(parent) { if e.hir_id == id { if let Some(span) = expr.span.find_ancestor_inside(block_span) { @@ -2220,30 +2212,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let local_parent = self.tcx.hir().parent_id(local_id); - let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) = - self.tcx.opt_hir_node(local_parent) + let Node::Param(hir::Param { hir_id: param_hir_id, .. }) = self.tcx.hir_node(local_parent) else { return None; }; let param_parent = self.tcx.hir().parent_id(*param_hir_id); - let Some(Node::Expr(hir::Expr { + let Node::Expr(hir::Expr { hir_id: expr_hir_id, kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }), .. - })) = self.tcx.opt_hir_node(param_parent) + }) = self.tcx.hir_node(param_parent) else { return None; }; let expr_parent = self.tcx.hir().parent_id(*expr_hir_id); - let hir = self.tcx.opt_hir_node(expr_parent); + let hir = self.tcx.hir_node(expr_parent); let closure_params_len = closure_fn_decl.inputs.len(); let ( - Some(Node::Expr(hir::Expr { + Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(method_path, receiver, ..), .. - })), + }), 1, ) = (hir, closure_params_len) else { @@ -2674,10 +2665,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool { if let hir::ExprKind::If(..) = expr.kind { let parent_id = self.tcx.hir().parent_id(expr.hir_id); - if let Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::If(_, _, Some(else_expr)), - .. - })) = self.tcx.opt_hir_node(parent_id) + if let Node::Expr(hir::Expr { + kind: hir::ExprKind::If(_, _, Some(else_expr)), .. + }) = self.tcx.hir_node(parent_id) { return else_expr.hir_id == expr.hir_id; } @@ -3067,7 +3057,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; let parent = self.tcx.hir().parent_id(expr.hir_id); - if let Some(hir::Node::ExprField(_)) = self.tcx.opt_hir_node(parent) { + if let hir::Node::ExprField(_) = self.tcx.hir_node(parent) { // Ignore `Foo { field: a..Default::default() }` return; } @@ -3146,7 +3136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::def::Res::Local(hir_id) = path.res else { return; }; - let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else { + let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else { return; }; let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) = diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 007df203f7117..81b8239351547 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -230,7 +230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind && let hir::def::Res::Local(hir_id) = path.res - && let Some(hir::Node::Pat(b)) = self.tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(b) = self.tcx.hir_node(hir_id) && let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id) && let Some(node) = self.tcx.hir().find_parent(p.hir_id) && let Some(decl) = node.fn_decl() @@ -2017,7 +2017,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { visitor.visit_body(body); let parent = self.tcx.hir().parent_id(seg1.hir_id); - if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent) + if let Node::Expr(call_expr) = self.tcx.hir_node(parent) && let Some(expr) = visitor.result && let Some(self_ty) = self.node_ty_opt(expr.hir_id) { @@ -3251,7 +3251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let parent = self.tcx.hir().parent_id(expr.hir_id); - if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent) + if let Node::Expr(call_expr) = self.tcx.hir_node(parent) && let hir::ExprKind::MethodCall( hir::PathSegment { ident: method_name, .. }, self_expr, diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs index b9b3ed53dae8f..34ce0ab1f8b98 100644 --- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs +++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs @@ -73,9 +73,7 @@ pub fn resolve_rvalue_scopes<'a, 'tcx>( debug!("start resolving rvalue scopes, def_id={def_id:?}"); debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates); for (&hir_id, candidate) in &scope_tree.rvalue_candidates { - let Some(Node::Expr(expr)) = tcx.opt_hir_node(hir_id) else { - bug!("hir node does not exist") - }; + let Node::Expr(expr) = tcx.hir_node(hir_id) else { bug!("hir node does not exist") }; record_rvalue_scope(&mut rvalue_scopes, expr, candidate); } rvalue_scopes diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index c4773a885218a..211109b59417a 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -972,9 +972,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Ok(mut s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) { if s.starts_with('$') { // Looks like a macro fragment. Try to find the real block. - if let Some(hir::Node::Expr(&hir::Expr { + if let hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Block(block, ..), .. - })) = self.tcx.opt_hir_node(body_id.hir_id) { + }) = self.tcx.hir_node(body_id.hir_id) { // If the body is a block (with `{..}`), we use the span of that block. // E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`. // Since we know it's a block, we know we can insert the `let _ = ..` without diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 59bed38ec2af1..dd9ed80ca7242 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2182,8 +2182,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let Some(tykind) = tykind && let hir::TyKind::Array(_, length) = tykind && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length - && let Some(span) = self.tcx.hir().opt_span(*hir_id) { + let span = self.tcx.hir().span(*hir_id); Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found }) } else { None diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 5ee0a606a5f57..9a9d13ed60825 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -687,7 +687,7 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi let res = hir_id == scope; trace!( "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}", - tcx.opt_hir_node(hir_id), + tcx.hir_node(hir_id), tcx.hir_node(opaque_hir_id), res ); diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index eabc1b953af1c..ed551658d91a9 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::Map; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; @@ -62,7 +61,7 @@ pub fn report_object_safety_error<'tcx>( err.span_label(span, format!("`{trait_str}` cannot be made into an object")); if let Some(hir_id) = hir_id - && let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id) + && let hir::Node::Ty(ty) = tcx.hir_node(hir_id) && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind { let mut hir_id = hir_id; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 64e19e0946fd0..dea61faef4af3 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -157,21 +157,15 @@ impl<'tcx> TyCtxt<'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> { - Some(self.hir_owner_nodes(id.owner).nodes[id.local_id].node) - } - /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. #[inline] pub fn opt_hir_node_by_def_id(self, id: LocalDefId) -> Option> { - self.opt_hir_node(self.opt_local_def_id_to_hir_id(id)?) + Some(self.hir_node(self.opt_local_def_id_to_hir_id(id)?)) } - /// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found. - #[track_caller] + /// Retrieves the `hir::Node` corresponding to `id`. pub fn hir_node(self, id: HirId) -> Node<'tcx> { - self.opt_hir_node(id).unwrap_or_else(|| bug!("couldn't find HIR node for hir id {id:?}")) + self.hir_owner_nodes(id.owner).nodes[id.local_id].node } /// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found. @@ -250,11 +244,12 @@ impl<'hir> Map<'hir> { } pub fn find_parent(self, hir_id: HirId) -> Option> { - self.tcx.opt_hir_node(self.opt_parent_id(hir_id)?) + Some(self.tcx.hir_node(self.opt_parent_id(hir_id)?)) } pub fn get_if_local(self, id: DefId) -> Option> { - id.as_local().and_then(|id| self.tcx.opt_hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?)) + id.as_local() + .and_then(|id| Some(self.tcx.hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?))) } pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { @@ -283,20 +278,12 @@ impl<'hir> Map<'hir> { #[track_caller] pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { - if let Some(node) = self.tcx.opt_hir_node(hir_id) { - node.fn_decl() - } else { - bug!("no node for hir_id `{}`", hir_id) - } + self.tcx.hir_node(hir_id).fn_decl() } #[track_caller] pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { - if let Some(node) = self.tcx.opt_hir_node(hir_id) { - node.fn_sig() - } else { - bug!("no node for hir_id `{}`", hir_id) - } + self.tcx.hir_node(hir_id).fn_sig() } #[track_caller] @@ -315,10 +302,7 @@ impl<'hir> Map<'hir> { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId { let parent = self.parent_id(hir_id); - assert!( - self.tcx.opt_hir_node(parent).is_some_and(|n| is_body_owner(n, hir_id)), - "{hir_id:?}" - ); + assert!(is_body_owner(self.tcx.hir_node(parent), hir_id), "{hir_id:?}"); parent } @@ -570,7 +554,7 @@ impl<'hir> Map<'hir> { /// until the crate root is reached. Prefer this over your own loop using `parent_id`. #[inline] pub fn parent_iter(self, current_id: HirId) -> impl Iterator)> { - self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.tcx.opt_hir_node(id)?))) + self.parent_id_iter(current_id).map(move |id| (id, self.tcx.hir_node(id))) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` @@ -622,7 +606,7 @@ impl<'hir> Map<'hir> { pub fn get_return_block(self, id: HirId) -> Option { let mut iter = self.parent_iter(id).peekable(); let mut ignore_tail = false; - if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.tcx.opt_hir_node(id) { + if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(id) { // When dealing with `return` statements, we don't care about climbing only tail // expressions. ignore_tail = true; @@ -775,8 +759,8 @@ impl<'hir> Map<'hir> { } pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> { - match self.tcx.opt_hir_node(id) { - Some(Node::Variant(variant)) => variant, + match self.tcx.hir_node(id) { + Node::Variant(variant) => variant, _ => bug!("expected variant, found {}", self.node_to_string(id)), } } @@ -794,18 +778,18 @@ impl<'hir> Map<'hir> { } pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> { - match self.tcx.opt_hir_node(id) { - Some(Node::Expr(expr)) => expr, + match self.tcx.hir_node(id) { + Node::Expr(expr) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)), } } #[inline] fn opt_ident(self, id: HirId) -> Option { - match self.tcx.opt_hir_node(id)? { + match self.tcx.hir_node(id) { Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident), // A `Ctor` doesn't have an identifier itself, but its parent - // struct/variant does. Compare with `hir::Map::opt_span`. + // struct/variant does. Compare with `hir::Map::span`. Node::Ctor(..) => match self.find_parent(id)? { Node::Item(item) => Some(item.ident), Node::Variant(variant) => Some(variant.ident), @@ -843,11 +827,6 @@ impl<'hir> Map<'hir> { /// Gets the span of the definition of the specified HIR node. /// This is used by `tcx.def_span`. pub fn span(self, hir_id: HirId) -> Span { - self.opt_span(hir_id) - .unwrap_or_else(|| bug!("hir::map::Map::span: id not in map: {:?}", hir_id)) - } - - pub fn opt_span(self, hir_id: HirId) -> Option { fn until_within(outer: Span, end: Span) -> Span { if let Some(end) = end.find_ancestor_inside(outer) { outer.with_hi(end.hi()) @@ -871,7 +850,7 @@ impl<'hir> Map<'hir> { } } - let span = match self.tcx.opt_hir_node(hir_id)? { + let span = match self.tcx.hir_node(hir_id) { // Function-like. Node::Item(Item { kind: ItemKind::Fn(sig, ..), span: outer_span, .. }) | Node::TraitItem(TraitItem { @@ -943,7 +922,7 @@ impl<'hir> Map<'hir> { ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()), _ => named_span(item.span, item.ident, None), }, - Node::Ctor(_) => return self.opt_span(self.parent_id(hir_id)), + Node::Ctor(_) => return self.span(self.parent_id(hir_id)), Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl_span, .. }), span, @@ -955,7 +934,7 @@ impl<'hir> Map<'hir> { _ => self.span_with_body(hir_id), }; debug_assert_eq!(span.ctxt(), self.span_with_body(hir_id).ctxt()); - Some(span) + span } /// Like `hir.span()`, but includes the body of items @@ -1058,8 +1037,8 @@ impl<'hir> Map<'hir> { } impl<'hir> intravisit::Map<'hir> for Map<'hir> { - fn find(&self, hir_id: HirId) -> Option> { - self.tcx.opt_hir_node(hir_id) + fn hir_node(&self, hir_id: HirId) -> Node<'hir> { + self.tcx.hir_node(hir_id) } fn body(&self, id: BodyId) -> &'hir Body<'hir> { @@ -1176,8 +1155,8 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default(); let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str()); - match map.tcx.opt_hir_node(id) { - Some(Node::Item(item)) => { + match map.tcx.hir_node(id) { + Node::Item(item) => { let item_str = match item.kind { ItemKind::ExternCrate(..) => "extern crate", ItemKind::Use(..) => "use", @@ -1205,10 +1184,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { }; format!("{id} ({item_str} {})", path_str(item.owner_id.def_id)) } - Some(Node::ForeignItem(item)) => { + Node::ForeignItem(item) => { format!("{id} (foreign item {})", path_str(item.owner_id.def_id)) } - Some(Node::ImplItem(ii)) => { + Node::ImplItem(ii) => { let kind = match ii.kind { ImplItemKind::Const(..) => "assoc const", ImplItemKind::Fn(..) => "method", @@ -1216,7 +1195,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { }; format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id)) } - Some(Node::TraitItem(ti)) => { + Node::TraitItem(ti) => { let kind = match ti.kind { TraitItemKind::Const(..) => "assoc constant", TraitItemKind::Fn(..) => "trait method", @@ -1225,41 +1204,40 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id)) } - Some(Node::Variant(variant)) => { + Node::Variant(variant) => { format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id)) } - Some(Node::Field(field)) => { + Node::Field(field) => { format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id)) } - Some(Node::AnonConst(_)) => node_str("const"), - Some(Node::ConstBlock(_)) => node_str("const"), - Some(Node::Expr(_)) => node_str("expr"), - Some(Node::ExprField(_)) => node_str("expr field"), - Some(Node::Stmt(_)) => node_str("stmt"), - Some(Node::PathSegment(_)) => node_str("path segment"), - Some(Node::Ty(_)) => node_str("type"), - Some(Node::TypeBinding(_)) => node_str("type binding"), - Some(Node::TraitRef(_)) => node_str("trait ref"), - Some(Node::Pat(_)) => node_str("pat"), - Some(Node::PatField(_)) => node_str("pattern field"), - Some(Node::Param(_)) => node_str("param"), - Some(Node::Arm(_)) => node_str("arm"), - Some(Node::Block(_)) => node_str("block"), - Some(Node::Infer(_)) => node_str("infer"), - Some(Node::Local(_)) => node_str("local"), - Some(Node::Ctor(ctor)) => format!( + Node::AnonConst(_) => node_str("const"), + Node::ConstBlock(_) => node_str("const"), + Node::Expr(_) => node_str("expr"), + Node::ExprField(_) => node_str("expr field"), + Node::Stmt(_) => node_str("stmt"), + Node::PathSegment(_) => node_str("path segment"), + Node::Ty(_) => node_str("type"), + Node::TypeBinding(_) => node_str("type binding"), + Node::TraitRef(_) => node_str("trait ref"), + Node::Pat(_) => node_str("pat"), + Node::PatField(_) => node_str("pattern field"), + Node::Param(_) => node_str("param"), + Node::Arm(_) => node_str("arm"), + Node::Block(_) => node_str("block"), + Node::Infer(_) => node_str("infer"), + Node::Local(_) => node_str("local"), + Node::Ctor(ctor) => format!( "{id} (ctor {})", ctor.ctor_def_id().map_or("".into(), |def_id| path_str(def_id)), ), - Some(Node::Lifetime(_)) => node_str("lifetime"), - Some(Node::GenericParam(param)) => { + Node::Lifetime(_) => node_str("lifetime"), + Node::GenericParam(param) => { format!("{id} (generic_param {})", path_str(param.def_id)) } - Some(Node::Crate(..)) => String::from("(root_crate)"), - Some(Node::WhereBoundPredicate(_)) => node_str("where bound predicate"), - Some(Node::ArrayLenInfer(_)) => node_str("array len infer"), - Some(Node::Err(_)) => node_str("error"), - None => format!("{id} (unknown node)"), + Node::Crate(..) => String::from("(root_crate)"), + Node::WhereBoundPredicate(_) => node_str("where bound predicate"), + Node::ArrayLenInfer(_) => node_str("array len infer"), + Node::Err(_) => node_str("error"), } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 94191df30a5e6..f66cd2370e3ee 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -12,7 +12,7 @@ use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; -use rustc_span::{ErrorGuaranteed, ExpnId, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, ExpnId}; /// Gather the LocalDefId for each item-like within a module, including items contained within /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. @@ -148,10 +148,7 @@ pub fn provide(providers: &mut Providers) { providers.hir_attrs = |tcx, id| { tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) }; - providers.def_span = |tcx, def_id| { - let hir_id = tcx.local_def_id_to_hir_id(def_id); - tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP) - }; + providers.def_span = |tcx, def_id| tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); providers.def_ident_span = |tcx, def_id| { let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.hir().opt_ident_span(hir_id) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e652c79d85157..ec704dec352da 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -827,10 +827,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.doc_attr_str_error(meta, "keyword"); return false; } - match self.tcx.opt_hir_node(hir_id).and_then(|node| match node { + let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, - }) { + }; + match item_kind { Some(ItemKind::Mod(module)) => { if !module.item_ids.is_empty() { self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() }); @@ -853,10 +854,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { - match self.tcx.opt_hir_node(hir_id).and_then(|node| match node { + let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, - }) { + }; + match item_kind { Some(ItemKind::Impl(i)) => { let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) || if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind { @@ -2221,8 +2223,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } else { // special case when `#[macro_export]` is applied to a macro 2.0 - let (macro_definition, _) = - self.tcx.opt_hir_node(hir_id).unwrap().expect_item().expect_macro(); + let (macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); let is_decl_macro = !macro_definition.macro_rules; if is_decl_macro { diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 0f8cc583b03cf..e10a22cdf31b9 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -134,7 +134,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { Err(hir::LoopIdError::UnresolvedLabel) => None, }; - if let Some(Node::Block(_)) = loop_id.and_then(|id| self.tcx.opt_hir_node(id)) { + if let Some(Node::Block(_)) = loop_id.map(|id| self.tcx.hir_node(id)) { return; } @@ -186,7 +186,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { match destination.target_id { Ok(loop_id) => { - if let Node::Block(block) = self.tcx.opt_hir_node(loop_id).unwrap() { + if let Node::Block(block) = self.tcx.hir_node(loop_id) { self.sess.dcx().emit_err(ContinueLabeledBlock { span: e.span, block_span: block.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 243f583aed825..a4d8cbb125c72 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -19,7 +19,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{Map, Visitor}; +use rustc_hir::intravisit::Visitor; use rustc_hir::is_range_literal; use rustc_hir::lang_items::LangItem; use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node}; @@ -774,7 +774,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if steps > 0 { // Don't care about `&mut` because `DerefMut` is used less // often and user will not expect that an autoderef happens. - if let Some(hir::Node::Expr(hir::Expr { + if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf( hir::BorrowKind::Ref, @@ -782,7 +782,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { expr, ), .. - })) = self.tcx.opt_hir_node(*arg_hir_id) + }) = self.tcx.hir_node(*arg_hir_id) { let derefs = "*".repeat(steps); err.span_suggestion_verbose( @@ -1199,7 +1199,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let Res::Local(hir_id) = path.res else { return; }; - let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else { + let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else { return; }; let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) = @@ -1786,7 +1786,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let Res::Local(hir_id) = path.res - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(hir_id) && let Some(hir::Node::Local(local)) = self.tcx.hir().find_parent(binding.hir_id) && let None = local.ty && let Some(binding_expr) = local.init @@ -2198,7 +2198,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let ty::FnPtr(found) = found.kind() else { return; }; - let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id) else { + let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else { return; }; let hir::ExprKind::Path(path) = arg.kind else { @@ -3186,8 +3186,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::VariableType(hir_id) => { let parent_node = tcx.hir().parent_id(hir_id); - match tcx.opt_hir_node(parent_node) { - Some(Node::Local(hir::Local { ty: Some(ty), .. })) => { + match tcx.hir_node(parent_node) { + Node::Local(hir::Local { ty: Some(ty), .. }) => { err.span_suggestion_verbose( ty.span.shrink_to_lo(), "consider borrowing here", @@ -3196,10 +3196,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); err.note("all local variables must have a statically known size"); } - Some(Node::Local(hir::Local { + Node::Local(hir::Local { init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }), .. - })) => { + }) => { // When encountering an assignment of an unsized trait, like // `let x = ""[..];`, provide a suggestion to borrow the initializer in // order to use have a slice instead. @@ -3211,7 +3211,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); err.note("all local variables must have a statically known size"); } - Some(Node::Param(param)) => { + Node::Param(param) => { err.span_suggestion_verbose( param.ty_span.shrink_to_lo(), "function arguments must have a statically known size, borrowed types \ @@ -3233,7 +3233,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let borrowed_msg = "function arguments must have a statically known size, borrowed \ types always have a known size"; if let Some(hir_id) = hir_id - && let Some(hir::Node::Param(param)) = self.tcx.hir().find(hir_id) + && let hir::Node::Param(param) = self.tcx.hir_node(hir_id) && let Some(item) = self.tcx.hir().find_parent(hir_id) && let Some(decl) = item.fn_decl() && let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span)) @@ -3247,7 +3247,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // param._ty_span ty = Some(t); } else if let Some(hir_id) = hir_id - && let Some(hir::Node::Ty(t)) = self.tcx.hir().find(hir_id) + && let hir::Node::Ty(t) = self.tcx.hir_node(hir_id) { ty = Some(t); } @@ -3958,7 +3958,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { call_hir_id: HirId, ) { let tcx = self.tcx; - if let Some(Node::Expr(expr)) = tcx.opt_hir_node(arg_hir_id) + if let Node::Expr(expr) = tcx.hir_node(arg_hir_id) && let Some(typeck_results) = &self.typeck_results { if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr { @@ -4074,9 +4074,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let parent_hir_id = self.tcx.hir().parent_id(binding.hir_id) - && let Some(hir::Node::Local(local)) = self.tcx.opt_hir_node(parent_hir_id) + && let hir::Node::Local(local) = self.tcx.hir_node(parent_hir_id) && let Some(binding_expr) = local.init { // If the expression we're calling on is a binding, we want to point at the @@ -4087,17 +4087,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.point_at_chain(expr, typeck_results, type_diffs, param_env, err); } } - let call_node = tcx.opt_hir_node(call_hir_id); - if let Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. - })) = call_node + let call_node = tcx.hir_node(call_hir_id); + if let Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. }) = + call_node { if Some(rcvr.span) == err.span.primary_span() { err.replace_span_with(path.ident.span, true); } } - if let Some(Node::Expr(expr)) = tcx.opt_hir_node(call_hir_id) { + if let Node::Expr(expr) = tcx.hir_node(call_hir_id) { if let hir::ExprKind::Call(hir::Expr { span, .. }, _) | hir::ExprKind::MethodCall( hir::PathSegment { ident: Ident { span, .. }, .. }, @@ -4334,7 +4333,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let Some(parent) = self.tcx.hir().find_parent(binding.hir_id) { // We've reached the root of the method call chain... 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 1ac0f172ef4c3..f6c352e7bcb4e 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 @@ -993,13 +993,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> Result<(), ErrorGuaranteed> { if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() - && let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id) + && let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) && let arg = arg.peel_borrows() && let hir::ExprKind::Path(hir::QPath::Resolved( None, hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) = arg.kind - && let Some(Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) + && let Node::Pat(pat) = self.tcx.hir_node(*hir_id) && let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span) && preds.contains(&obligation.predicate) { @@ -1037,10 +1037,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id); - let body_id = match self.tcx.opt_hir_node(hir_id) { - Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => { - body_id - } + let body_id = match self.tcx.hir_node(hir_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id, _ => return false, }; let mut v = V { search_span: span, found: None }; @@ -1163,7 +1161,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let Some(parent) = self.tcx.hir().find_parent(binding.hir_id) { // We've reached the root of the method call chain... diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index b055e355b788a..8ee35db56f8dd 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -94,7 +94,7 @@ impl<'tcx> SpanMapVisitor<'tcx> { /// Used to generate links on items' definition to go to their documentation page. pub(crate) fn extract_info_from_hir_id(&mut self, hir_id: HirId) { - if let Some(Node::Item(item)) = self.tcx.opt_hir_node(hir_id) { + if let Node::Item(item) = self.tcx.hir_node(hir_id) { if let Some(span) = self.tcx.def_ident_span(item.owner_id) { let cspan = clean::Span::new(span); // If the span isn't from the current crate, we ignore it. @@ -199,7 +199,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { if !span.overlaps(m.spans.inner_span) { // Now that we confirmed it's a file import, we want to get the span for the module // name only and not all the "mod foo;". - if let Some(Node::Item(item)) = self.tcx.opt_hir_node(id) { + if let Node::Item(item) = self.tcx.hir_node(id) { self.matches.insert( item.ident.span, LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)), diff --git a/src/tools/clippy/clippy_lints/src/absolute_paths.rs b/src/tools/clippy/clippy_lints/src/absolute_paths.rs index 3822b83b4bc64..8ba661afeeb6f 100644 --- a/src/tools/clippy/clippy_lints/src/absolute_paths.rs +++ b/src/tools/clippy/clippy_lints/src/absolute_paths.rs @@ -62,7 +62,7 @@ impl LateLintPass<'_> for AbsolutePaths { } = self; if !path.span.from_expansion() - && let Some(node) = cx.tcx.opt_hir_node(hir_id) + && let node = cx.tcx.hir_node(hir_id) && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _))) && let [first, rest @ ..] = path.segments // Handle `::std` diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs index 91bad8256ecb1..0f29743856ac9 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -68,9 +68,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let map = cx.tcx.hir(); - if let Some(parent_id) = map.opt_parent_id(expr.hir_id) - && let Some(parent) = cx.tcx.opt_hir_node(parent_id) - { + if let Some(parent_id) = map.opt_parent_id(expr.hir_id) { + let parent = cx.tcx.hir_node(parent_id); let expr = match parent { Node::Block(block) => { if let Some(parent_expr) = block.expr { diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index bb86b6f30759c..81d0def4322d3 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -144,8 +144,7 @@ pub(super) fn check<'tcx>( if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) { if let Some(id) = path_to_local(cast_expr) - && let Some(span) = cx.tcx.hir().opt_span(id) - && !span.eq_ctxt(cast_expr.span) + && !cx.tcx.hir().span(id).eq_ctxt(cast_expr.span) { // Binding context is different than the identifiers context. // Weird macro wizardry could be involved here. diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index 6b0423200d765..b0f46f5c646cf 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -195,7 +195,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::Default, def_id) && let impl_item_hir = child.id.hir_id() - && let Some(Node::ImplItem(impl_item)) = cx.tcx.opt_hir_node(impl_item_hir) + && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir) && let ImplItemKind::Fn(_, b) = &impl_item.kind && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b) && let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() diff --git a/src/tools/clippy/clippy_lints/src/empty_drop.rs b/src/tools/clippy/clippy_lints/src/empty_drop.rs index 1d2b907b94821..74db250b3ae92 100644 --- a/src/tools/clippy/clippy_lints/src/empty_drop.rs +++ b/src/tools/clippy/clippy_lints/src/empty_drop.rs @@ -42,7 +42,7 @@ impl LateLintPass<'_> for EmptyDrop { }) = item.kind && trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait() && let impl_item_hir = child.id.hir_id() - && let Some(Node::ImplItem(impl_item)) = cx.tcx.opt_hir_node(impl_item_hir) + && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir) && let ImplItemKind::Fn(_, b) = &impl_item.kind && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b) && let func_expr = peel_blocks(func_expr) diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index b7776263060be..218d7c6c01ae1 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -123,11 +123,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { // TODO: Replace with Map::is_argument(..) when it's fixed fn is_argument(tcx: TyCtxt<'_>, id: HirId) -> bool { - match tcx.opt_hir_node(id) { - Some(Node::Pat(Pat { + match tcx.hir_node(id) { + Node::Pat(Pat { kind: PatKind::Binding(..), .. - })) => (), + }) => (), _ => return false, } diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index e8c1e5db35e00..de048fef5f224 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -111,7 +111,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) // Find id of the local that expr_end_of_block resolves to && let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind && let Res::Local(expr_res) = expr_path.res - && let Some(Node::Pat(res_pat)) = cx.tcx.opt_hir_node(expr_res) + && let Node::Pat(res_pat) = cx.tcx.hir_node(expr_res) // Find id of the local we found in the block && let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index 5417c13d07967..252be30c4e27d 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -248,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { // Checking for slice indexing && let parent_id = map.parent_id(expr.hir_id) - && let Some(hir::Node::Expr(parent_expr)) = cx.tcx.opt_hir_node(parent_id) + && let hir::Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id) && let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind && let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr) && let Ok(index_value) = index_value.try_into() @@ -256,7 +256,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { // Make sure that this slice index is read only && let maybe_addrof_id = map.parent_id(parent_id) - && let Some(hir::Node::Expr(maybe_addrof_expr)) = cx.tcx.opt_hir_node(maybe_addrof_id) + && let hir::Node::Expr(maybe_addrof_expr) = cx.tcx.hir_node(maybe_addrof_id) && let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind { use_info.index_use.push((index_value, map.span(parent_expr.hir_id))); diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index c1ab020117ca6..27d85cde5320a 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -147,9 +147,9 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { && let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder()) { - let (name, kind) = match cx.tcx.opt_hir_node(ty_hir_id) { - Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"), - Some(Node::Item(x)) => match x.kind { + let (name, kind) = match cx.tcx.hir_node(ty_hir_id) { + Node::ForeignItem(x) => (x.ident.name, "extern type"), + Node::Item(x) => match x.kind { ItemKind::Struct(..) => (x.ident.name, "struct"), ItemKind::Enum(..) => (x.ident.name, "enum"), ItemKind::Union(..) => (x.ident.name, "union"), diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index 920a887a6fd1b..5f015db2b33bf 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -63,7 +63,7 @@ pub(super) fn check<'tcx>( && let PatKind::Binding(bind_ann, ..) = pat.kind && !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut)) && let parent_node = cx.tcx.hir().parent_id(hir_id) - && let Some(Node::Local(parent_let_expr)) = cx.tcx.opt_hir_node(parent_node) + && let Node::Local(parent_let_expr) = cx.tcx.hir_node(parent_node) && let Some(init) = parent_let_expr.init { match init.kind { diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs index 71a83a68db933..e1768c6d97641 100644 --- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { // Also ensures the const is nonzero since zero can't be a divisor && const1 == const2 && const2 == const3 && let Some(hir_id) = path_to_local(expr3) - && let Some(Node::Pat(_)) = cx.tcx.opt_hir_node(hir_id) + && let Node::Pat(_) = cx.tcx.hir_node(hir_id) { // Apply only to params or locals with annotated types match cx.tcx.hir().find_parent(hir_id) { diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs index 9251130a30549..7339362193e54 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs @@ -44,7 +44,7 @@ pub(super) fn check<'tcx>( // add note if not multi-line span_lint_and_then(cx, FILTER_NEXT, expr.span, msg, |diag| { let (applicability, pat) = if let Some(id) = path_to_local(recv) - && let Some(hir::Node::Pat(pat)) = cx.tcx.opt_hir_node(id) + && let hir::Node::Pat(pat) = cx.tcx.hir_node(id) && let hir::PatKind::Binding(BindingAnnotation(_, Mutability::Not), _, ident, _) = pat.kind { (Applicability::Unspecified, Some((pat.span, ident))) diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 624597ffca949..ab36f854fcb1d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -135,7 +135,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { if let Res::Local(local_id) = path.res - && let Some(Node::Pat(pat)) = self.cx.tcx.opt_hir_node(local_id) + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) && let PatKind::Binding(_, local_id, ..) = pat.kind { self.identifiers.insert(local_id); @@ -166,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> { && let ExprKind::Path(ref path) = expr.kind && let QPath::Resolved(_, path) = path && let Res::Local(local_id) = path.res - && let Some(Node::Pat(pat)) = self.cx.tcx.opt_hir_node(local_id) + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) && let PatKind::Binding(_, local_id, ..) = pat.kind && self.identifiers.contains(&local_id) { 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 2f9f04832a750..70cc43e266c6d 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -91,7 +91,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { let node = if hir_id.local_id == ItemLocalId::from_u32(0) { // In this case, we can just use `find`, `Owner`'s `node` field is private anyway so we can't // reimplement it even if we wanted to - cx.tcx.opt_hir_node(hir_id) + Some(cx.tcx.hir_node(hir_id)) } else { let owner = cx.tcx.hir_owner_nodes(hir_id.owner); owner.nodes.get(hir_id.local_id).copied().map(|p| p.node) diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index 195ce17629a71..b593e48ae2e16 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -213,11 +213,8 @@ fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) { if parent_id == cur_id { break; } - let Some(parent_node) = vis.cx.tcx.opt_hir_node(parent_id) else { - break; - }; - let stop_early = match parent_node { + let stop_early = match vis.cx.tcx.hir_node(parent_id) { Node::Expr(expr) => check_expr(vis, expr), Node::Stmt(stmt) => check_stmt(vis, stmt), Node::Item(_) => { diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index f8365deebd46e..10ab380ba1bc5 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -453,7 +453,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { if parent_id == cur_expr.hir_id { break; } - if let Some(Node::Expr(parent_expr)) = cx.tcx.opt_hir_node(parent_id) { + if let Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id) { match &parent_expr.kind { ExprKind::AddrOf(..) => { // `&e` => `e` must be referenced. diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index 7a351dab2d458..07806b182f22b 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -76,8 +76,8 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { match of_trait { Some(trait_ref) => { let mut methods_in_trait: BTreeSet = - if let Some(Node::TraitRef(TraitRef { path, .. })) = - cx.tcx.opt_hir_node(trait_ref.hir_ref_id) + if let Node::TraitRef(TraitRef { path, .. }) = + cx.tcx.hir_node(trait_ref.hir_ref_id) && let Res::Def(DefKind::Trait, did) = path.res { // FIXME: if diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index 98f3235af10a0..fc5a45dd56d6b 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { if let Some(self_def) = self_ty.ty_adt_def() && let Some(self_local_did) = self_def.did().as_local() && let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did) - && let Some(Node::Item(x)) = cx.tcx.opt_hir_node(self_id) + && let Node::Item(x) = cx.tcx.hir_node(self_id) && let type_name = x.ident.name.as_str().to_lowercase() && (impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace('_', "") == type_name) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 4e499ff4cc612..3f936009e44ec 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -177,10 +177,10 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr /// canonical binding `HirId`. pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { let hir = cx.tcx.hir(); - if let Some(Node::Pat(pat)) = cx.tcx.opt_hir_node(hir_id) + if let Node::Pat(pat) = cx.tcx.hir_node(hir_id) && matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..)) && let parent = hir.parent_id(hir_id) - && let Some(Node::Local(local)) = cx.tcx.opt_hir_node(parent) + && let Node::Local(local) = cx.tcx.hir_node(parent) { return local.init; } @@ -1327,7 +1327,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio let map = &cx.tcx.hir(); let enclosing_node = map .get_enclosing_scope(hir_id) - .and_then(|enclosing_id| cx.tcx.opt_hir_node(enclosing_id)); + .map(|enclosing_id| cx.tcx.hir_node(enclosing_id)); enclosing_node.and_then(|node| match node { Node::Block(block) => Some(block), Node::Item(&Item { @@ -2696,10 +2696,10 @@ impl<'tcx> ExprUseNode<'tcx> { )), Self::Return(id) => { let hir_id = cx.tcx.local_def_id_to_hir_id(id.def_id); - if let Some(Node::Expr(Expr { + if let Node::Expr(Expr { kind: ExprKind::Closure(c), .. - })) = cx.tcx.opt_hir_node(hir_id) + }) = cx.tcx.hir_node(hir_id) { match c.fn_decl.output { FnRetTy::DefaultReturn(_) => None, From 3e8c8d8d3417295fefa325f35db2a5da54617c8d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 31 Jan 2024 21:55:10 +0300 Subject: [PATCH 615/676] hir: Add some FIXMEs for future work --- compiler/rustc_ast_lowering/src/index.rs | 1 + compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_hir/src/intravisit.rs | 1 + compiler/rustc_middle/src/hir/map/mod.rs | 3 +++ 4 files changed, 6 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index ff3870cf11b92..11aa6b250b129 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -265,6 +265,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_path_segment(&mut self, path_segment: &'hir PathSegment<'hir>) { + // FIXME: walk path segment with `path_segment.hir_id` parent. self.insert(path_segment.ident.span, path_segment.hir_id, Node::PathSegment(path_segment)); intravisit::walk_path_segment(self, path_segment); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2468e91e8b945..dcc67af7588f0 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3493,6 +3493,7 @@ pub enum Node<'hir> { Crate(&'hir Mod<'hir>), Infer(&'hir InferArg), WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>), + // FIXME: Merge into `Node::Infer`. ArrayLenInfer(&'hir InferArg), // Span by reference to minimize `Node`'s size #[allow(rustc::pass_by_value)] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 574b372be2ba5..52e1109ff9215 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -669,6 +669,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { match len { + // FIXME: Use `visit_infer` here. ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), ArrayLen::Body(c) => visitor.visit_anon_const(c), } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index dea61faef4af3..bf72aac10332e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -222,6 +222,9 @@ impl<'hir> Map<'hir> { /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`]. pub fn opt_parent_id(self, id: HirId) -> Option { if id.local_id == ItemLocalId::from_u32(0) { + // FIXME: This function never returns `None` right now, and the parent chain end is + // determined by checking for `parent(id) == id`. This function should return `None` + // for the crate root instead. Some(self.tcx.hir_owner_parent(id.owner)) } else { let owner = self.tcx.hir_owner_nodes(id.owner); From a59d00674a6b04ba1eaa5e0c3cf00ddb0346296b Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 7 Feb 2024 15:26:57 +0800 Subject: [PATCH 616/676] Add parallel rustc ui tests --- src/tools/tidy/src/ui_tests.rs | 2 +- .../cache-after-waiting-issue-111528.rs | 16 ++++++++++++++ .../cache-after-waiting-issue-111528.stderr | 8 +++++++ .../export-symbols-deadlock-issue-118205-2.rs | 7 ++++++ .../export-symbols-deadlock-issue-118205.rs | 22 +++++++++++++++++++ tests/ui/parallel-rustc/hello_world.rs | 6 +++++ .../read-stolen-value-issue-111520.rs | 18 +++++++++++++++ 7 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs create mode 100644 tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr create mode 100644 tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs create mode 100644 tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs create mode 100644 tests/ui/parallel-rustc/hello_world.rs create mode 100644 tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index e7b1ccf6a0299..4a44c40debd22 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1819; -const ROOT_ENTRY_LIMIT: usize = 870; +const ROOT_ENTRY_LIMIT: usize = 871; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs new file mode 100644 index 0000000000000..148a59240f99a --- /dev/null +++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs @@ -0,0 +1,16 @@ +// compile-flags: -Z threads=16 +// build-fail + +#![crate_type="rlib"] +#![allow(warnings)] + +#[export_name="fail"] +pub fn a() { +} + +#[export_name="fail"] +pub fn b() { +//~^ Error symbol `fail` is already defined +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr new file mode 100644 index 0000000000000..7963165e31b0a --- /dev/null +++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/cache-after-waiting-issue-111528.rs:12:1 + | +LL | pub fn b() { + | ^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs new file mode 100644 index 0000000000000..8240b249018e2 --- /dev/null +++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs @@ -0,0 +1,7 @@ +// compile-flags:-C extra-filename=-1 -Z threads=16 +// no-prefer-dynamic +// build-pass +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs new file mode 100644 index 0000000000000..691c36cfc9ec4 --- /dev/null +++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs @@ -0,0 +1,22 @@ +// compile-flags: -Z threads=16 +// build-pass + +pub static GLOBAL: isize = 3; + +static GLOBAL0: isize = 4; + +pub static GLOBAL2: &'static isize = &GLOBAL0; + +pub fn verify_same(a: &'static isize) { + let a = a as *const isize as usize; + let b = &GLOBAL as *const isize as usize; + assert_eq!(a, b); +} + +pub fn verify_same2(a: &'static isize) { + let a = a as *const isize as usize; + let b = GLOBAL2 as *const isize as usize; + assert_eq!(a, b); +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/hello_world.rs b/tests/ui/parallel-rustc/hello_world.rs new file mode 100644 index 0000000000000..53e95c890ef52 --- /dev/null +++ b/tests/ui/parallel-rustc/hello_world.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z threads=8 +// run-pass + +fn main() { + println!("Hello world!"); +} diff --git a/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs new file mode 100644 index 0000000000000..1907348cf09dc --- /dev/null +++ b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z threads=16 +// run-pass + +#[repr(transparent)] +struct Sched { + i: i32, +} +impl Sched { + extern "C" fn get(self) -> i32 { self.i } +} + +fn main() { + let s = Sched { i: 4 }; + let f = || -> i32 { + s.get() + }; + println!("f: {}", f()); +} From 0a50dba50bedd24377bd1066da3b4b7066df4d28 Mon Sep 17 00:00:00 2001 From: bohan Date: Wed, 7 Feb 2024 15:43:19 +0800 Subject: [PATCH 617/676] docs: also check the inline stmt during redundant link check --- src/librustdoc/clean/mod.rs | 2 +- .../passes/lint/redundant_explicit_links.rs | 49 ++++++++++++------- tests/rustdoc-ui/issues/issue-120444-1.rs | 17 +++++++ tests/rustdoc-ui/issues/issue-120444-1.stderr | 22 +++++++++ tests/rustdoc-ui/issues/issue-120444-2.rs | 17 +++++++ tests/rustdoc-ui/issues/issue-120444-2.stderr | 22 +++++++++ 6 files changed, 111 insertions(+), 18 deletions(-) create mode 100644 tests/rustdoc-ui/issues/issue-120444-1.rs create mode 100644 tests/rustdoc-ui/issues/issue-120444-1.stderr create mode 100644 tests/rustdoc-ui/issues/issue-120444-2.rs create mode 100644 tests/rustdoc-ui/issues/issue-120444-2.stderr diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3bac71dbc24e2..b8e0d75e7dc37 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -82,7 +82,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< // but there's already an item with the same namespace and same name. Rust gives // priority to the not-imported one, so we should, too. items.extend(doc.items.values().flat_map(|(item, renamed, import_id)| { - // First, lower everything other than imports. + // First, lower everything other than glob imports. if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { return Vec::new(); } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 9069098bf1a37..f7bc546470796 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -7,6 +7,7 @@ use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res}; use rustc_hir::HirId; use rustc_lint_defs::Applicability; use rustc_resolve::rustdoc::source_span_for_markdown_range; +use rustc_span::def_id::DefId; use rustc_span::Symbol; use crate::clean::utils::find_nearest_parent_module; @@ -33,17 +34,22 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { return; } - if item.link_names(&cx.cache).is_empty() { - // If there's no link names in this item, - // then we skip resolution querying to - // avoid from panicking. - return; + if let Some(item_id) = item.def_id() { + check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); } + if let Some(item_id) = item.inline_stmt_id { + check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); + } +} - let Some(item_id) = item.def_id() else { - return; - }; - let Some(local_item_id) = item_id.as_local() else { +fn check_redundant_explicit_link_for_did<'md>( + cx: &DocContext<'_>, + item: &Item, + did: DefId, + hir_id: HirId, + doc: &'md str, +) { + let Some(local_item_id) = did.as_local() else { return; }; @@ -53,12 +59,26 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { return; } let is_private = !cx.render_options.document_private - && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id); + && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, did); if is_private { return; } - check_redundant_explicit_link(cx, item, hir_id, &doc); + let module_id = match cx.tcx.def_kind(did) { + DefKind::Mod if item.inner_docs(cx.tcx) => did, + _ => find_nearest_parent_module(cx.tcx, did).unwrap(), + }; + + let Some(resolutions) = + cx.tcx.resolutions(()).doc_link_resolutions.get(&module_id.expect_local()) + else { + // If there's no resolutions in this module, + // then we skip resolution querying to + // avoid from panicking. + return; + }; + + check_redundant_explicit_link(cx, item, hir_id, &doc, &resolutions); } fn check_redundant_explicit_link<'md>( @@ -66,6 +86,7 @@ fn check_redundant_explicit_link<'md>( item: &Item, hir_id: HirId, doc: &'md str, + resolutions: &DocLinkResMap, ) -> Option<()> { let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); let mut offset_iter = Parser::new_with_broken_link_callback( @@ -74,12 +95,6 @@ fn check_redundant_explicit_link<'md>( Some(&mut broken_line_callback), ) .into_offset_iter(); - let item_id = item.def_id()?; - let module_id = match cx.tcx.def_kind(item_id) { - DefKind::Mod if item.inner_docs(cx.tcx) => item_id, - _ => find_nearest_parent_module(cx.tcx, item_id).unwrap(), - }; - let resolutions = cx.tcx.doc_link_resolutions(module_id); while let Some((event, link_range)) = offset_iter.next() { match event { diff --git a/tests/rustdoc-ui/issues/issue-120444-1.rs b/tests/rustdoc-ui/issues/issue-120444-1.rs new file mode 100644 index 0000000000000..25d0111a7b763 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-1.rs @@ -0,0 +1,17 @@ +// compile-flags: --document-private-items + +#![deny(rustdoc::redundant_explicit_links)] + +mod webdavfs { + pub struct A; + pub struct B; +} + +/// [`Vfs`][crate::Vfs] +pub use webdavfs::A; +//~^^ error: redundant explicit link target + +/// [`Vfs`] +pub use webdavfs::B; + +pub struct Vfs; diff --git a/tests/rustdoc-ui/issues/issue-120444-1.stderr b/tests/rustdoc-ui/issues/issue-120444-1.stderr new file mode 100644 index 0000000000000..7bc56b4263f26 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-1.stderr @@ -0,0 +1,22 @@ +error: redundant explicit link target + --> $DIR/issue-120444-1.rs:10:13 + | +LL | /// [`Vfs`][crate::Vfs] + | ----- ^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/issue-120444-1.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [`Vfs`] + | ~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc-ui/issues/issue-120444-2.rs b/tests/rustdoc-ui/issues/issue-120444-2.rs new file mode 100644 index 0000000000000..d13bf88462435 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-2.rs @@ -0,0 +1,17 @@ +// compile-flags: --document-private-items + +#![deny(rustdoc::redundant_explicit_links)] + +pub mod webdavfs { + pub struct A; + pub struct B; +} + +/// [`Vfs`][crate::Vfs] +pub use webdavfs::A; +//~^^ error: redundant explicit link target + +/// [`Vfs`] +pub use webdavfs::B; + +pub struct Vfs; diff --git a/tests/rustdoc-ui/issues/issue-120444-2.stderr b/tests/rustdoc-ui/issues/issue-120444-2.stderr new file mode 100644 index 0000000000000..310bf08e2b525 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-2.stderr @@ -0,0 +1,22 @@ +error: redundant explicit link target + --> $DIR/issue-120444-2.rs:10:13 + | +LL | /// [`Vfs`][crate::Vfs] + | ----- ^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/issue-120444-2.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [`Vfs`] + | ~~~~~~~ + +error: aborting due to 1 previous error + From e55df623ead33023fe6c4488064e5d5e4e141b9e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 6 Feb 2024 17:40:11 +1100 Subject: [PATCH 618/676] Remove an `unchecked_claim_error_was_emitted` call. When `catch_fatal_errors` catches a `FatalErrorMarker`, it returns an `ErrorGuaranteed` that is conjured out of thin air with `unchecked_claim_error_was_emitted`. But that `ErrorGuaranteed` is never used. This commit changes it to instead conjure a `FatalError` out of thin air. (A non-deprecated action!) This makes more sense because `FatalError` and `FatalErrorMarker` are a natural pairing -- a `FatalErrorMarker` is created by calling `FatalError::raise`, so this is effectively getting back the original `FatalError`. This requires a tiny change in `catch_with_exit_code`. The old result of the `catch_fatal_errors` call there was `Result, ErrorGuaranteed>` which could be `flatten`ed into `Result<(), ErrorGuaranteed>`. The new result of the `catch_fatal_errors` calls is `Result, FatalError>`, which can't be `flatten`ed but is still easily matched for the success case. --- compiler/rustc_driver_impl/src/lib.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 5903c43ae98af..519bde988200e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -24,7 +24,9 @@ use rustc_data_structures::profiling::{ get_resident_set_size, print_time_passes_entry, TimePassesFormat, }; use rustc_errors::registry::Registry; -use rustc_errors::{markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, PResult}; +use rustc_errors::{ + markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult, +}; use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; @@ -1231,11 +1233,10 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { /// The compiler currently unwinds with a special sentinel value to abort /// compilation on fatal errors. This function catches that sentinel and turns /// the panic into a `Result` instead. -pub fn catch_fatal_errors R, R>(f: F) -> Result { +pub fn catch_fatal_errors R, R>(f: F) -> Result { catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| { if value.is::() { - #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + FatalError } else { panic::resume_unwind(value); } @@ -1245,9 +1246,9 @@ pub fn catch_fatal_errors R, R>(f: F) -> Result interface::Result<()>) -> i32 { - match catch_fatal_errors(f).flatten() { - Ok(()) => EXIT_SUCCESS, - Err(_) => EXIT_FAILURE, + match catch_fatal_errors(f) { + Ok(Ok(())) => EXIT_SUCCESS, + _ => EXIT_FAILURE, } } From e6794ddfb00e14b29b3befc5bc054a15094321b7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 6 Feb 2024 20:47:47 +1100 Subject: [PATCH 619/676] rustdoc: make `main` more like rustc's. By making non-unicode arguments a fatal error instead of a warning, we don't need to handle what comes after, which avoids the need for an `unchecked_claim_error_was_emitted` call. --- src/librustdoc/lib.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8c10f14116a0c..0fe3adadba347 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -177,13 +177,16 @@ pub fn main() { init_logging(&early_dcx); rustc_driver::init_logger(&early_dcx, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")); - let exit_code = rustc_driver::catch_with_exit_code(|| match get_args(&early_dcx) { - Some(args) => main_args(&mut early_dcx, &args, using_internal_features), - _ => - { - #[allow(deprecated)] - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - } + let exit_code = rustc_driver::catch_with_exit_code(|| { + let args = env::args_os() + .enumerate() + .map(|(i, arg)| { + arg.into_string().unwrap_or_else(|arg| { + early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}")) + }) + }) + .collect::>(); + main_args(&mut early_dcx, &args, using_internal_features) }); process::exit(exit_code); } @@ -219,19 +222,6 @@ fn init_logging(early_dcx: &EarlyDiagCtxt) { tracing::subscriber::set_global_default(subscriber).unwrap(); } -fn get_args(early_dcx: &EarlyDiagCtxt) -> Option> { - env::args_os() - .enumerate() - .map(|(i, arg)| { - arg.into_string() - .map_err(|arg| { - early_dcx.early_warn(format!("Argument {i} is not valid Unicode: {arg:?}")); - }) - .ok() - }) - .collect() -} - fn opts() -> Vec { let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable; let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable; From 83adf883a20fc7531e886996ce07b8555c943fba Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Feb 2024 09:01:49 +1100 Subject: [PATCH 620/676] rustdoc: remove `unchecked_claim_error_was_emitted` call in `main_args`. `main_args` calls `from_matches`, which does lots of initialization. If anything goes wrong, `from_matches` emits an error message and returns `Err(1)` (or `Err(3)`). `main_args` then turns the `Err(1)` into `Err(ErrorGuaranteed)`, because that's what `catch_with_exit_code` requires on error. But `catch_with_exit_code` doesn't do anything with the `ErrorGuaranteed`, it just exits with `EXIT_FAILURE`. We can avoid the creation of the `ErrorGuaranteed` (which requires an undesirable `unchecked_claim_error_was_emitted` call), by changing `from_matches` to instead eagerly abort if anything goes wrong. The behaviour from the user's point of view is the same: an early abort with an `EXIT_FAILURE` exit code. And we can also simplify `from_matches` to return an `Option` instead of a `Result`: - Old `Err(0)` case --> `None` - Old `Err(_)` case --> fatal error. This requires similar changes to `ScrapeExamplesOptions::new` and `load_call_locations`. --- src/librustdoc/config.rs | 96 +++++++++++-------------------- src/librustdoc/lib.rs | 11 +--- src/librustdoc/scrape_examples.rs | 49 +++++++--------- 3 files changed, 54 insertions(+), 102 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 3f7f9270b2da0..c46047aa0dbad 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -323,20 +323,20 @@ impl Options { early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches, args: Vec, - ) -> Result<(Options, RenderOptions), i32> { + ) -> Option<(Options, RenderOptions)> { // Check for unstable options. nightly_options::check_nightly_options(early_dcx, matches, &opts()); if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") { crate::usage("rustdoc"); - return Err(0); + return None; } else if matches.opt_present("version") { rustc_driver::version!(&early_dcx, "rustdoc", matches); - return Err(0); + return None; } if rustc_driver::describe_flag_categories(early_dcx, &matches) { - return Err(0); + return None; } let color = config::parse_color(early_dcx, matches); @@ -382,7 +382,7 @@ impl Options { } } - return Err(0); + return None; } let mut emit = Vec::new(); @@ -390,10 +390,7 @@ impl Options { for kind in list.split(',') { match kind.parse() { Ok(kind) => emit.push(kind), - Err(()) => { - dcx.err(format!("unrecognized emission type: {kind}")); - return Err(1); - } + Err(()) => dcx.fatal(format!("unrecognized emission type: {kind}")), } } } @@ -403,7 +400,7 @@ impl Options { && !matches.opt_present("show-coverage") && !nightly_options::is_unstable_enabled(matches) { - early_dcx.early_fatal( + dcx.fatal( "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)", ); } @@ -420,10 +417,7 @@ impl Options { } let paths = match theme::load_css_paths(content) { Ok(p) => p, - Err(e) => { - dcx.err(e); - return Err(1); - } + Err(e) => dcx.fatal(e), }; let mut errors = 0; @@ -442,9 +436,9 @@ impl Options { } } if errors != 0 { - return Err(1); + dcx.fatal("[check-theme] one or more tests failed"); } - return Err(0); + return None; } let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); @@ -452,11 +446,9 @@ impl Options { let input = PathBuf::from(if describe_lints { "" // dummy, this won't be used } else if matches.free.is_empty() { - dcx.err("missing file operand"); - return Err(1); + dcx.fatal("missing file operand"); } else if matches.free.len() > 1 { - dcx.err("too many file operands"); - return Err(1); + dcx.fatal("too many file operands"); } else { &matches.free[0] }); @@ -466,10 +458,7 @@ impl Options { let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { Ok(ex) => ex, - Err(err) => { - dcx.err(err); - return Err(1); - } + Err(err) => dcx.fatal(err), }; let default_settings: Vec> = vec![ @@ -526,16 +515,14 @@ impl Options { let no_run = matches.opt_present("no-run"); if !should_test && no_run { - dcx.err("the `--test` flag must be passed to enable `--no-run`"); - return Err(1); + dcx.fatal("the `--test` flag must be passed to enable `--no-run`"); } let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s)); let output = matches.opt_str("output").map(|s| PathBuf::from(&s)); let output = match (out_dir, output) { (Some(_), Some(_)) => { - dcx.err("cannot use both 'out-dir' and 'output' at once"); - return Err(1); + dcx.fatal("cannot use both 'out-dir' and 'output' at once"); } (Some(out_dir), None) => out_dir, (None, Some(output)) => output, @@ -549,8 +536,7 @@ impl Options { if let Some(ref p) = extension_css { if !p.is_file() { - dcx.err("option --extend-css argument must be a file"); - return Err(1); + dcx.fatal("option --extend-css argument must be a file"); } } @@ -566,31 +552,25 @@ impl Options { } let paths = match theme::load_css_paths(content) { Ok(p) => p, - Err(e) => { - dcx.err(e); - return Err(1); - } + Err(e) => dcx.fatal(e), }; for (theme_file, theme_s) in matches.opt_strs("theme").iter().map(|s| (PathBuf::from(&s), s.to_owned())) { if !theme_file.is_file() { - dcx.struct_err(format!("invalid argument: \"{theme_s}\"")) + dcx.struct_fatal(format!("invalid argument: \"{theme_s}\"")) .with_help("arguments to --theme must be files") .emit(); - return Err(1); } if theme_file.extension() != Some(OsStr::new("css")) { - dcx.struct_err(format!("invalid argument: \"{theme_s}\"")) + dcx.struct_fatal(format!("invalid argument: \"{theme_s}\"")) .with_help("arguments to --theme must have a .css extension") .emit(); - return Err(1); } let (success, ret) = theme::test_theme_against(&theme_file, &paths, &dcx); if !success { - dcx.err(format!("error loading theme file: \"{theme_s}\"")); - return Err(1); + dcx.fatal(format!("error loading theme file: \"{theme_s}\"")); } else if !ret.is_empty() { dcx.struct_warn(format!( "theme file \"{theme_s}\" is missing CSS rules from the default theme", @@ -620,22 +600,18 @@ impl Options { edition, &None, ) else { - return Err(3); + dcx.fatal("`ExternalHtml::load` failed"); }; match matches.opt_str("r").as_deref() { Some("rust") | None => {} - Some(s) => { - dcx.err(format!("unknown input format: {s}")); - return Err(1); - } + Some(s) => dcx.fatal(format!("unknown input format: {s}")), } let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s)); if let Some(ref index_page) = index_page { if !index_page.is_file() { - dcx.err("option `--index-page` argument must be a file"); - return Err(1); + dcx.fatal("option `--index-page` argument must be a file"); } } @@ -646,8 +622,7 @@ impl Options { let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) { Ok(types) => types, Err(e) => { - dcx.err(format!("unknown crate type: {e}")); - return Err(1); + dcx.fatal(format!("unknown crate type: {e}")); } }; @@ -655,18 +630,13 @@ impl Options { Some(s) => match OutputFormat::try_from(s.as_str()) { Ok(out_fmt) => { if !out_fmt.is_json() && show_coverage { - dcx.struct_err( + dcx.fatal( "html output format isn't supported for the --show-coverage option", - ) - .emit(); - return Err(1); + ); } out_fmt } - Err(e) => { - dcx.err(e); - return Err(1); - } + Err(e) => dcx.fatal(e), }, None => OutputFormat::default(), }; @@ -709,16 +679,14 @@ impl Options { let html_no_source = matches.opt_present("html-no-source"); if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) { - dcx.struct_err( + dcx.fatal( "--generate-link-to-definition option can only be used with HTML output format", - ) - .emit(); - return Err(1); + ); } - let scrape_examples_options = ScrapeExamplesOptions::new(matches, &dcx)?; + let scrape_examples_options = ScrapeExamplesOptions::new(matches, &dcx); let with_examples = matches.opt_strs("with-examples"); - let call_locations = crate::scrape_examples::load_call_locations(with_examples, &dcx)?; + let call_locations = crate::scrape_examples::load_call_locations(with_examples, &dcx); let unstable_features = rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref()); @@ -793,7 +761,7 @@ impl Options { no_emit_shared: false, html_no_source, }; - Ok((options, render_options)) + Some((options, render_options)) } /// Returns `true` if the file given as `self.input` is a Markdown file. diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0fe3adadba347..097bbeb6d2857 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -720,15 +720,8 @@ fn main_args( // Note that we discard any distinction between different non-zero exit // codes from `from_matches` here. let (options, render_options) = match config::Options::from_matches(early_dcx, &matches, args) { - Ok(opts) => opts, - Err(code) => { - return if code == 0 { - Ok(()) - } else { - #[allow(deprecated)] - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - }; - } + Some(opts) => opts, + None => return Ok(()), }; let diag = diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index b7d9c16f34837..9c9b386edda7c 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -38,28 +38,23 @@ pub(crate) struct ScrapeExamplesOptions { } impl ScrapeExamplesOptions { - pub(crate) fn new( - matches: &getopts::Matches, - dcx: &rustc_errors::DiagCtxt, - ) -> Result, i32> { + pub(crate) fn new(matches: &getopts::Matches, dcx: &rustc_errors::DiagCtxt) -> Option { let output_path = matches.opt_str("scrape-examples-output-path"); let target_crates = matches.opt_strs("scrape-examples-target-crate"); let scrape_tests = matches.opt_present("scrape-tests"); match (output_path, !target_crates.is_empty(), scrape_tests) { - (Some(output_path), true, _) => Ok(Some(ScrapeExamplesOptions { + (Some(output_path), true, _) => Some(ScrapeExamplesOptions { output_path: PathBuf::from(output_path), target_crates, scrape_tests, - })), + }), (Some(_), false, _) | (None, true, _) => { - dcx.err("must use --scrape-examples-output-path and --scrape-examples-target-crate together"); - Err(1) + dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate together"); } (None, false, true) => { - dcx.err("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests"); - Err(1) + dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests"); } - (None, false, false) => Ok(None), + (None, false, false) => None, } } } @@ -342,24 +337,20 @@ pub(crate) fn run( pub(crate) fn load_call_locations( with_examples: Vec, dcx: &rustc_errors::DiagCtxt, -) -> Result { - let inner = || { - let mut all_calls: AllCallLocations = FxHashMap::default(); - for path in with_examples { - let bytes = fs::read(&path).map_err(|e| format!("{e} (for path {path})"))?; - let mut decoder = MemDecoder::new(&bytes, 0); - let calls = AllCallLocations::decode(&mut decoder); - - for (function, fn_calls) in calls.into_iter() { - all_calls.entry(function).or_default().extend(fn_calls.into_iter()); - } - } +) -> AllCallLocations { + let mut all_calls: AllCallLocations = FxHashMap::default(); + for path in with_examples { + let bytes = match fs::read(&path) { + Ok(bytes) => bytes, + Err(e) => dcx.fatal(format!("failed to load examples: {e}")), + }; + let mut decoder = MemDecoder::new(&bytes, 0); + let calls = AllCallLocations::decode(&mut decoder); - Ok(all_calls) - }; + for (function, fn_calls) in calls.into_iter() { + all_calls.entry(function).or_default().extend(fn_calls.into_iter()); + } + } - inner().map_err(|e: String| { - dcx.err(format!("failed to load examples: {e}")); - 1 - }) + all_calls } From 97c157fe1e52eeabe14a64865b4731794a23393a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Feb 2024 10:26:50 +1100 Subject: [PATCH 621/676] Tighten up `ErrorGuaranteed` handling. - In `emit_producing_error_guaranteed`, only allow `Level::Error`. - In `emit_diagnostic`, only produce `ErrorGuaranteed` for `Level` and `DelayedBug`. (Not `Bug` or `Fatal`. They don't need it, because the relevant `emit` methods abort.) - Add/update various comments. --- compiler/rustc_errors/src/diagnostic_builder.rs | 16 ++++++++++------ compiler/rustc_errors/src/lib.rs | 14 ++++++++++---- compiler/rustc_span/src/lib.rs | 5 ++--- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index faff7f0b52673..e484bef0e0bc9 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -99,16 +99,20 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } /// `ErrorGuaranteed::emit_producing_guarantee` uses this. - // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { let diag = self.take_diag(); - // Only allow a guarantee if the `level` wasn't switched to a - // non-error. The field isn't `pub`, but the whole `Diagnostic` can be - // overwritten with a new one, thanks to `DerefMut`. + // The only error levels that produce `ErrorGuaranteed` are + // `Error` and `DelayedBug`. But `DelayedBug` should never occur here + // because delayed bugs have their level changed to `Bug` when they are + // actually printed, so they produce an ICE. + // + // (Also, even though `level` isn't `pub`, the whole `Diagnostic` could + // be overwritten with a new one thanks to `DerefMut`. So this assert + // protects against that, too.) assert!( - diag.is_error(), - "emitted non-error ({:?}) diagnostic from `DiagnosticBuilder`", + matches!(diag.level, Level::Error | Level::DelayedBug), + "invalid diagnostic level ({:?})", diag.level, ); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 7c62e3aa42281..74cccda6cbff6 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -931,6 +931,7 @@ impl DiagCtxt { /// This excludes lint errors and delayed bugs. pub fn has_errors(&self) -> Option { self.inner.borrow().has_errors().then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) @@ -942,6 +943,7 @@ impl DiagCtxt { let inner = self.inner.borrow(); let result = inner.has_errors() || inner.lint_err_count > 0; result.then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) @@ -954,6 +956,7 @@ impl DiagCtxt { let result = inner.has_errors() || inner.lint_err_count > 0 || !inner.delayed_bugs.is_empty(); result.then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) @@ -1238,6 +1241,7 @@ impl DiagCtxtInner { } } + // Return value is only `Some` if the level is `Error` or `DelayedBug`. fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { assert!(diagnostic.level.can_be_top_or_sub().0); @@ -1316,6 +1320,7 @@ impl DiagCtxtInner { !self.emitted_diagnostics.insert(diagnostic_hash) }; + let level = diagnostic.level; let is_error = diagnostic.is_error(); let is_lint = diagnostic.is_lint.is_some(); @@ -1352,6 +1357,7 @@ impl DiagCtxtInner { self.emitter.emit_diagnostic(diagnostic); } + if is_error { if is_lint { self.lint_err_count += 1; @@ -1359,11 +1365,11 @@ impl DiagCtxtInner { self.err_count += 1; } self.panic_if_treat_err_as_bug(); + } - #[allow(deprecated)] - { - guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); - } + #[allow(deprecated)] + if level == Level::Error { + guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); } }); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ea6766ea583be..1a1e1de6734ac 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2477,9 +2477,8 @@ where pub struct ErrorGuaranteed(()); impl ErrorGuaranteed { - /// To be used only if you really know what you are doing... ideally, we would find a way to - /// eliminate all calls to this method. - #[deprecated = "`Session::span_delayed_bug` should be preferred over this function"] + /// Don't use this outside of `DiagCtxtInner::emit_diagnostic`! + #[deprecated = "should only be used in `DiagCtxtInner::emit_diagnostic`"] pub fn unchecked_claim_error_was_emitted() -> Self { ErrorGuaranteed(()) } From 6889fe3806fa44addca89193e5c45ced8c7f532d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Feb 2024 19:30:59 +1100 Subject: [PATCH 622/676] Rename `unchecked_claim_error_was_emitted` as `unchecked_error_guaranteed`. It's more to-the-point. --- compiler/rustc_errors/src/lib.rs | 10 +++++----- compiler/rustc_span/src/lib.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 74cccda6cbff6..ec5029e505f96 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -933,7 +933,7 @@ impl DiagCtxt { self.inner.borrow().has_errors().then(|| { // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } @@ -945,7 +945,7 @@ impl DiagCtxt { result.then(|| { // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } @@ -958,7 +958,7 @@ impl DiagCtxt { result.then(|| { // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } @@ -1286,7 +1286,7 @@ impl DiagCtxtInner { let backtrace = std::backtrace::Backtrace::capture(); self.delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); #[allow(deprecated)] - return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); + return Some(ErrorGuaranteed::unchecked_error_guaranteed()); } GoodPathDelayedBug => { let backtrace = std::backtrace::Backtrace::capture(); @@ -1369,7 +1369,7 @@ impl DiagCtxtInner { #[allow(deprecated)] if level == Level::Error { - guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); + guaranteed = Some(ErrorGuaranteed::unchecked_error_guaranteed()); } }); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 1a1e1de6734ac..bcf04a71ae223 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2479,7 +2479,7 @@ pub struct ErrorGuaranteed(()); impl ErrorGuaranteed { /// Don't use this outside of `DiagCtxtInner::emit_diagnostic`! #[deprecated = "should only be used in `DiagCtxtInner::emit_diagnostic`"] - pub fn unchecked_claim_error_was_emitted() -> Self { + pub fn unchecked_error_guaranteed() -> Self { ErrorGuaranteed(()) } } From c5e6df0c78afb787ae5b121ee8394baa21bca555 Mon Sep 17 00:00:00 2001 From: klensy Date: Wed, 7 Feb 2024 10:47:52 +0300 Subject: [PATCH 623/676] MirPass: make name more const --- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/mir/mod.rs | 8 ++++++-- compiler/rustc_middle/src/util/common.rs | 16 ++++++++++++++++ compiler/rustc_mir_transform/src/pass_manager.rs | 12 ++---------- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index ddfb2ece39f10..9f1609a559568 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -30,6 +30,7 @@ #![feature(assert_matches)] #![feature(box_patterns)] #![feature(core_intrinsics)] +#![feature(const_type_name)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(coroutines)] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index c9e69253701c5..4ba96464c0e2f 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -140,8 +140,12 @@ fn to_profiler_name(type_name: &'static str) -> &'static str { /// loop that goes over each available MIR and applies `run_pass`. pub trait MirPass<'tcx> { fn name(&self) -> &'static str { - let name = std::any::type_name::(); - if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name } + // FIXME Simplify the implementation once more `str` methods get const-stable. + // See copypaste in `MirLint` + const { + let name = std::any::type_name::(); + crate::util::common::c_name(name) + } } fn profiler_name(&self) -> &'static str { diff --git a/compiler/rustc_middle/src/util/common.rs b/compiler/rustc_middle/src/util/common.rs index df101a2f6e4c6..dd3a36c7bf853 100644 --- a/compiler/rustc_middle/src/util/common.rs +++ b/compiler/rustc_middle/src/util/common.rs @@ -65,3 +65,19 @@ pub fn indenter() -> Indenter { debug!(">>"); Indenter { _cannot_construct_outside_of_this_module: () } } + +// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` +pub const fn c_name(name: &'static str) -> &'static str { + // FIXME Simplify the implementation once more `str` methods get const-stable. + // and inline into call site + let bytes = name.as_bytes(); + let mut i = bytes.len(); + while i > 0 && bytes[i - 1] != b':' { + i = i - 1; + } + let (_, bytes) = bytes.split_at(i); + match std::str::from_utf8(bytes) { + Ok(name) => name, + Err(_) => name, + } +} diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index c1ef2b9f887fb..211a4057ff000 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -8,18 +8,10 @@ use crate::{lint::lint_body, validate, MirPass}; pub trait MirLint<'tcx> { fn name(&self) -> &'static str { // FIXME Simplify the implementation once more `str` methods get const-stable. + // See copypaste in `MirPass` const { let name = std::any::type_name::(); - let bytes = name.as_bytes(); - let mut i = bytes.len(); - while i > 0 && bytes[i - 1] != b':' { - i = i - 1; - } - let (_, bytes) = bytes.split_at(i); - match std::str::from_utf8(bytes) { - Ok(name) => name, - Err(_) => name, - } + rustc_middle::util::common::c_name(name) } } From 58d70d6805565ec2208a88f2d8d414fc940beed6 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 31 Jan 2024 06:06:50 +0100 Subject: [PATCH 624/676] Simplify `impl_zeroable_primitive` macro. --- library/core/src/num/nonzero.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1124719fc8df1..ea922970b92d8 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -35,7 +35,7 @@ mod private { pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {} macro_rules! impl_zeroable_primitive { - ($NonZero:ident ( $primitive:ty )) => { + ($primitive:ty) => { #[unstable( feature = "nonzero_internals", reason = "implementation detail which may disappear or be replaced at any time", @@ -52,18 +52,18 @@ macro_rules! impl_zeroable_primitive { }; } -impl_zeroable_primitive!(NonZeroU8(u8)); -impl_zeroable_primitive!(NonZeroU16(u16)); -impl_zeroable_primitive!(NonZeroU32(u32)); -impl_zeroable_primitive!(NonZeroU64(u64)); -impl_zeroable_primitive!(NonZeroU128(u128)); -impl_zeroable_primitive!(NonZeroUsize(usize)); -impl_zeroable_primitive!(NonZeroI8(i8)); -impl_zeroable_primitive!(NonZeroI16(i16)); -impl_zeroable_primitive!(NonZeroI32(i32)); -impl_zeroable_primitive!(NonZeroI64(i64)); -impl_zeroable_primitive!(NonZeroI128(i128)); -impl_zeroable_primitive!(NonZeroIsize(isize)); +impl_zeroable_primitive!(u8); +impl_zeroable_primitive!(u16); +impl_zeroable_primitive!(u32); +impl_zeroable_primitive!(u64); +impl_zeroable_primitive!(u128); +impl_zeroable_primitive!(usize); +impl_zeroable_primitive!(i8); +impl_zeroable_primitive!(i16); +impl_zeroable_primitive!(i32); +impl_zeroable_primitive!(i64); +impl_zeroable_primitive!(i128); +impl_zeroable_primitive!(isize); /// A value that is known not to equal zero. /// From a67b72c74e8b59eb0eeb48767cb37e6c1a139329 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 22 Jan 2024 18:04:05 +0100 Subject: [PATCH 625/676] Make `NonZero` constructors generic. --- library/core/src/num/nonzero.rs | 155 +++++++++++++++++--------------- 1 file changed, 84 insertions(+), 71 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index ea922970b92d8..8cbbc2aa1a24c 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -83,6 +83,90 @@ impl_zeroable_primitive!(isize); #[rustc_diagnostic_item = "NonZero"] pub struct NonZero(T); +impl NonZero +where + T: ZeroablePrimitive, +{ + /// Creates a non-zero if the given value is not zero. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] + #[rustc_allow_const_fn_unstable(const_refs_to_cell)] + #[must_use] + #[inline] + pub const fn new(n: T) -> Option { + // SAFETY: Memory layout optimization guarantees that `Option>` has + // the same layout and size as `T`, with `0` representing `None`. + unsafe { crate::mem::transmute_copy(&n) } + } + + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behaviour if the value is zero. + /// + /// # Safety + /// + /// The value must not be zero. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] + #[must_use] + #[inline] + pub const unsafe fn new_unchecked(n: T) -> Self { + match Self::new(n) { + Some(n) => n, + None => { + // SAFETY: The caller guarantees that `n` is non-zero, so this is unreachable. + unsafe { + crate::intrinsics::assert_unsafe_precondition!( + "NonZero::new_unchecked requires the argument to be non-zero", + () => false + ); + + crate::hint::unreachable_unchecked() + } + } + } + } + + /// Converts a reference to a non-zero mutable reference + /// if the referenced value is not zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub fn from_mut(n: &mut T) -> Option<&mut Self> { + // SAFETY: Memory layout optimization guarantees that `Option>` has + // the same layout and size as `T`, with `0` representing `None`. + let opt_n = unsafe { &mut *(n as *mut T as *mut Option) }; + + opt_n.as_mut() + } + + /// Converts a mutable reference to a non-zero mutable reference + /// without checking whether the referenced value is non-zero. + /// This results in undefined behavior if the referenced value is zero. + /// + /// # Safety + /// + /// The referenced value must not be zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub unsafe fn from_mut_unchecked(n: &mut T) -> &mut Self { + match Self::from_mut(n) { + Some(n) => n, + None => { + // SAFETY: The caller guarantees that `n` references a value that is non-zero, so this is unreachable. + unsafe { + crate::intrinsics::assert_unsafe_precondition!( + "NonZero::from_mut_unchecked requires the argument to dereference as non-zero", + () => false + ); + + crate::hint::unreachable_unchecked() + } + } + } + } +} + macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( @@ -100,7 +184,6 @@ macro_rules! impl_nonzero_fmt { macro_rules! nonzero_integer { ( #[$stability:meta] - #[$const_new_unchecked_stability:meta] Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, $(UnsignedNonZero = $UnsignedNonZero:ident,)? @@ -143,74 +226,6 @@ macro_rules! nonzero_integer { pub type $Ty = NonZero<$Int>; impl $Ty { - /// Creates a non-zero without checking whether the value is non-zero. - /// This results in undefined behaviour if the value is zero. - /// - /// # Safety - /// - /// The value must not be zero. - #[$stability] - #[$const_new_unchecked_stability] - #[must_use] - #[inline] - pub const unsafe fn new_unchecked(n: $Int) -> Self { - crate::panic::debug_assert_nounwind!( - n != 0, - concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") - ); - // SAFETY: this is guaranteed to be safe by the caller. - unsafe { - Self(n) - } - } - - /// Creates a non-zero if the given value is not zero. - #[$stability] - #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] - #[must_use] - #[inline] - pub const fn new(n: $Int) -> Option { - if n != 0 { - // SAFETY: we just checked that there's no `0` - Some(unsafe { Self(n) }) - } else { - None - } - } - - /// Converts a primitive mutable reference to a non-zero mutable reference - /// without checking whether the referenced value is non-zero. - /// This results in undefined behavior if `*n` is zero. - /// - /// # Safety - /// The referenced value must not be currently zero. - #[unstable(feature = "nonzero_from_mut", issue = "106290")] - #[must_use] - #[inline] - pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self { - // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero. - unsafe { - let n_alias = &mut *n; - core::intrinsics::assert_unsafe_precondition!( - concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"), - (n_alias: &mut $Int) => *n_alias != 0 - ); - &mut *(n as *mut $Int as *mut Self) - } - } - - /// Converts a primitive mutable reference to a non-zero mutable reference - /// if the referenced integer is not zero. - #[unstable(feature = "nonzero_from_mut", issue = "106290")] - #[must_use] - #[inline] - pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { - // SAFETY: Self is repr(transparent), and the value is non-zero. - // As long as the returned reference is alive, - // the user cannot `*n = 0` directly. - (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) }) - } - /// Returns the value as a primitive type. #[$stability] #[inline] @@ -724,7 +739,6 @@ macro_rules! nonzero_integer { (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => { nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] - #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] Self = $Ty, Primitive = unsigned $Int, UnsignedPrimitive = $Int, @@ -735,7 +749,6 @@ macro_rules! nonzero_integer { (Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => { nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] - #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] Self = $Ty, Primitive = signed $Int, $($rest)* From fd9202109be6971f1a03cc632c6027b25130cfb5 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Wed, 7 Feb 2024 02:19:12 +0100 Subject: [PATCH 626/676] add test for pretty printing trait objects --- tests/ui/traits/object/pretty.rs | 31 +++++++ tests/ui/traits/object/pretty.stderr | 124 +++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 tests/ui/traits/object/pretty.rs create mode 100644 tests/ui/traits/object/pretty.stderr diff --git a/tests/ui/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs new file mode 100644 index 0000000000000..625c651d5f75a --- /dev/null +++ b/tests/ui/traits/object/pretty.rs @@ -0,0 +1,31 @@ +// Test for pretty-printing trait object types. + +trait Super { + type Assoc; +} +trait Any: Super {} +trait Fixed: Super {} +trait FixedSub: Fixed {} + +trait SuperGeneric<'a> { + type Assoc; +} +trait AnyGeneric<'a>: SuperGeneric<'a> {} +trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc = &'a u8> {} +trait FixedGeneric2<'a>: Super {} +trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc = &'a u8> {} + +fn dyn_super(x: &dyn Super) { x } //~ERROR mismatched types +fn dyn_any(x: &dyn Any) { x } //~ERROR mismatched types +fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types +fn dyn_fixed_multi(x: &dyn Fixed) { x } //~ERROR mismatched types +fn dyn_fixed_sub(x: &dyn FixedSub) { x } //~ERROR mismatched types + +fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>) { x } //~ERROR mismatched types +fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>) { x } //~ERROR mismatched types +fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } //~ERROR mismatched types +fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } //~ERROR mismatched types +fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>) { x } //~ERROR mismatched types +fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types + +fn main() {} diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr new file mode 100644 index 0000000000000..2fa87e7a6fe54 --- /dev/null +++ b/tests/ui/traits/object/pretty.stderr @@ -0,0 +1,124 @@ +error[E0308]: mismatched types + --> $DIR/pretty.rs:18:43 + | +LL | fn dyn_super(x: &dyn Super) { x } + | - ^ expected `()`, found `&dyn Super` + | | + | help: try adding a return type: `-> &dyn Super` + | + = note: expected unit type `()` + found reference `&dyn Super` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:19:39 + | +LL | fn dyn_any(x: &dyn Any) { x } + | - ^ expected `()`, found `&dyn Any` + | | + | help: try adding a return type: `-> &dyn Any` + | + = note: expected unit type `()` + found reference `&dyn Any` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:20:31 + | +LL | fn dyn_fixed(x: &dyn Fixed) { x } + | - ^ expected `()`, found `&dyn Fixed` + | | + | help: try adding a return type: `-> &dyn Fixed` + | + = note: expected unit type `()` + found reference `&dyn Fixed` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:21:50 + | +LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } + | - ^ expected `()`, found `&dyn Fixed` + | | + | help: try adding a return type: `-> &dyn Fixed` + | + = note: expected unit type `()` + found reference `&dyn Fixed` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:22:38 + | +LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } + | - ^ expected `()`, found `&dyn FixedSub` + | | + | help: try adding a return type: `-> &dyn FixedSub` + | + = note: expected unit type `()` + found reference `&dyn FixedSub` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:24:74 + | +LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>) { x } + | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, for<'a> Assoc = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> SuperGeneric<'a, for<'a> Assoc = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:25:70 + | +LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>) { x } + | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, for<'a> Assoc = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> AnyGeneric<'a, for<'a> Assoc = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:26:60 + | +LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:27:60 + | +LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric2<'a, Assoc = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a, for<'a> Assoc = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric2<'a, for<'a> Assoc = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:28:78 + | +LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = ..., Assoc = ...>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &u8, for<'a> Assoc = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &u8, for<'a> Assoc = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:29:40 + | +LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } + | - ^ expected `()`, found `&dyn FixedHrtb` + | | + | help: try adding a return type: `-> &dyn FixedHrtb Assoc = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn FixedHrtb Assoc = &'a u8>` + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. From 0f323b24b22cdda444749238649518bad68c0c15 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 7 Feb 2024 14:00:21 +0000 Subject: [PATCH 627/676] Associated types in traits don't necessarily have a type that we can visit This prevents ICEs from happening in the future when this code path is actually used --- compiler/rustc_ty_utils/src/sig_types.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index b155a4ac87b9f..b0389052cccb8 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -42,11 +42,10 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( DefKind::TyAlias {..} | DefKind::AssocTy | // Walk over the type of the item DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { - let span = match tcx.hir_node_by_def_id(item).ty() { - Some(ty) => ty.span, - _ => tcx.def_span(item), - }; - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { + // Associated types in traits don't necessarily have a type that we can visit + visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())?; + } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } From 0b97d18f71a0756d5390e717269170ed2ba2755b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 7 Feb 2024 14:00:49 +0000 Subject: [PATCH 628/676] extern types don't have any types to visit --- compiler/rustc_ty_utils/src/sig_types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index b0389052cccb8..7435c78beb7cc 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -88,7 +88,6 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( } } | DefKind::Variant - | DefKind::ForeignTy | DefKind::TyParam | DefKind::ConstParam | DefKind::Ctor(_, _) @@ -102,6 +101,7 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // These don't have any types. | DefKind::ExternCrate | DefKind::ForeignMod + | DefKind::ForeignTy | DefKind::Macro(_) | DefKind::GlobalAsm | DefKind::Mod From b998b515e9b6a8568d18a7155f75a408860a19a3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 7 Feb 2024 14:05:34 +0000 Subject: [PATCH 629/676] Actually walk fields of Adt definitions --- compiler/rustc_ty_utils/src/sig_types.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 7435c78beb7cc..c32aaa89f495e 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -4,7 +4,7 @@ use std::ops::ControlFlow; use rustc_hir::{def::DefKind, def_id::LocalDefId}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; use rustc_type_ir::visit::TypeVisitable; @@ -58,7 +58,16 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Look at field types DefKind::Struct | DefKind::Union | DefKind::Enum => { let span = tcx.def_ident_span(item).unwrap(); - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + let ty = tcx.type_of(item).instantiate_identity(); + visitor.visit(span, ty); + let ty::Adt(def, args) = ty.kind() else { + span_bug!(span, "invalid type for {kind:?}: {:#?}", ty.kind()) + }; + for field in def.all_fields() { + let span = tcx.def_ident_span(field.did).unwrap(); + let ty = field.ty(tcx, args); + visitor.visit(span, ty); + } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } From 4389a1cc42a1822d9b2398095dac6d9d92753667 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 18 Jul 2023 07:22:46 +0000 Subject: [PATCH 630/676] Stop using `hir_ty_to_ty` in rustc_privacy --- Cargo.lock | 1 + compiler/rustc_privacy/Cargo.toml | 1 + compiler/rustc_privacy/src/lib.rs | 103 ++++++----- compiler/rustc_ty_utils/src/lib.rs | 2 +- compiler/rustc_ty_utils/src/sig_types.rs | 4 +- tests/ui/dyn-keyword/dyn-2018-edition-lint.rs | 8 - .../dyn-keyword/dyn-2018-edition-lint.stderr | 60 +------ ...esh-lifetime-from-bare-trait-obj-114664.rs | 4 - ...lifetime-from-bare-trait-obj-114664.stderr | 30 +--- .../allowed-group-warn-by-default-lint.rs | 4 - .../allowed-group-warn-by-default-lint.stderr | 30 +--- tests/ui/lint/force-warn/cap-lints-allow.rs | 4 - .../ui/lint/force-warn/cap-lints-allow.stderr | 30 +--- ...-group-allowed-cli-warn-by-default-lint.rs | 4 - ...up-allowed-cli-warn-by-default-lint.stderr | 30 +--- .../lint-group-allowed-lint-group.rs | 4 - .../lint-group-allowed-lint-group.stderr | 30 +--- ...lint-group-allowed-warn-by-default-lint.rs | 4 - ...-group-allowed-warn-by-default-lint.stderr | 30 +--- tests/ui/lint/lint-stability-deprecated.rs | 3 - .../ui/lint/lint-stability-deprecated.stderr | 170 ++++++++---------- .../assoc_type_bounds_sized_unnecessary.rs | 2 - ...assoc_type_bounds_sized_unnecessary.stderr | 20 +-- .../associated-item-privacy-trait.stderr | 22 +-- ...ssociated-item-privacy-type-binding.stderr | 8 +- .../privacy/private-type-in-interface.stderr | 8 +- tests/ui/privacy/struct-field-type.rs | 10 ++ tests/ui/privacy/struct-field-type.stderr | 21 +++ tests/ui/suggestions/issue-61963.rs | 10 -- tests/ui/suggestions/issue-61963.stderr | 74 +------- ...riority-lint-ambiguous_associated_items.rs | 3 - ...ity-lint-ambiguous_associated_items.stderr | 22 +-- 32 files changed, 191 insertions(+), 565 deletions(-) create mode 100644 tests/ui/privacy/struct-field-type.rs create mode 100644 tests/ui/privacy/struct-field-type.stderr diff --git a/Cargo.lock b/Cargo.lock index 29c8c7ef00404..300cc02330f97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4374,6 +4374,7 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", + "rustc_ty_utils", "tracing", ] diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index 90803c20d4312..e7a32771f350d 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -16,5 +16,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_ty_utils = { path = "../rustc_ty_utils" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a37d8822480af..eaec09cfbc234 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -21,7 +21,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, PatKind}; +use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind}; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgs; @@ -173,6 +173,10 @@ where { type BreakTy = V::BreakTy; + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { + self.visit_clause(p.as_clause().unwrap()) + } + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { let tcx = self.def_id_visitor.tcx(); // GenericArgs are not visited here because they are visited below @@ -1076,6 +1080,14 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { } } +impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> { + type BreakTy = (); + fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow<()> { + self.span = span; + value.visit_with(&mut self.skeleton()) + } +} + impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_nested_body(&mut self, body_id: hir::BodyId) { let old_maybe_typeck_results = @@ -1086,18 +1098,15 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { self.span = hir_ty.span; - if let Some(typeck_results) = self.maybe_typeck_results { - // Types in bodies. - if self.visit(typeck_results.node_type(hir_ty.hir_id)).is_break() { - return; - } - } else { - // Types in signatures. - // FIXME: This is very ineffective. Ideally each HIR type should be converted - // into a semantic type only once and the result should be cached somehow. - if self.visit(rustc_hir_analysis::hir_ty_to_ty(self.tcx, hir_ty)).is_break() { - return; - } + if self + .visit( + self.maybe_typeck_results + .unwrap_or_else(|| span_bug!(hir_ty.span, "`hir::Ty` outside of a body")) + .node_type(hir_ty.hir_id), + ) + .is_break() + { + return; } intravisit::walk_ty(self, hir_ty); @@ -1105,52 +1114,23 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { self.span = inf.span; - if let Some(typeck_results) = self.maybe_typeck_results { - if let Some(ty) = typeck_results.node_type_opt(inf.hir_id) { - if self.visit(ty).is_break() { - return; - } - } else { - // FIXME: check types of const infers here. + if let Some(ty) = self + .maybe_typeck_results + .unwrap_or_else(|| span_bug!(inf.span, "`hir::InferArg` outside of a body")) + .node_type_opt(inf.hir_id) + { + if self.visit(ty).is_break() { + return; } } else { - span_bug!(self.span, "`hir::InferArg` outside of a body"); + // FIXME: check types of const infers here. } intravisit::walk_inf(self, inf); } fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) { self.span = trait_ref.path.span; - if self.maybe_typeck_results.is_some() { - // Privacy of traits in bodies is checked as a part of trait object types. - } else { - let bounds = rustc_hir_analysis::hir_trait_to_predicates( - self.tcx, - trait_ref, - // NOTE: This isn't really right, but the actual type doesn't matter here. It's - // just required by `ty::TraitRef`. - self.tcx.types.never, - ); - - for (clause, _) in bounds.clauses() { - match clause.kind().skip_binder() { - ty::ClauseKind::Trait(trait_predicate) => { - if self.visit_trait(trait_predicate.trait_ref).is_break() { - return; - } - } - ty::ClauseKind::Projection(proj_predicate) => { - let term = self.visit(proj_predicate.term); - if term.is_break() - || self.visit_projection_ty(proj_predicate.projection_ty).is_break() - { - return; - } - } - _ => {} - } - } - } + // Privacy of traits in bodies is checked as a part of trait object types. intravisit::walk_trait_ref(self, trait_ref); } @@ -1727,7 +1707,26 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { // inferred types of expressions and patterns. let span = tcx.def_span(module_def_id); let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span }; - tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor); + + let module = tcx.hir_module_items(module_def_id); + for def_id in module.definitions() { + rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor); + + if let Some(body_id) = tcx.hir().maybe_body_owned_by(def_id) { + visitor.visit_nested_body(body_id); + } + } + + for id in module.items() { + if let ItemKind::Impl(i) = tcx.hir().item(id).kind { + if let Some(item) = i.of_trait { + let trait_ref = tcx.impl_trait_ref(id.owner_id.def_id).unwrap(); + let trait_ref = trait_ref.instantiate_identity(); + visitor.span = item.path.span; + visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path()); + } + } + } } fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 51acb99d29b58..4eb2b9cfe54e8 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -37,7 +37,7 @@ mod layout_sanity_check; mod needs_drop; mod opaque_types; mod representability; -mod sig_types; +pub mod sig_types; mod structural_match; mod ty; diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index c32aaa89f495e..38cc558380cd8 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; use rustc_type_ir::visit::TypeVisitable; -pub(crate) trait SpannedTypeVisitor<'tcx> { +pub trait SpannedTypeVisitor<'tcx> { type BreakTy = !; fn visit( &mut self, @@ -17,7 +17,7 @@ pub(crate) trait SpannedTypeVisitor<'tcx> { ) -> ControlFlow; } -pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( +pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( tcx: TyCtxt<'tcx>, item: LocalDefId, visitor: &mut V, diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs b/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs index a074b5fa5f7aa..23ca36b71e00f 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs @@ -6,14 +6,6 @@ fn function(x: &SomeTrait, y: Box) { //~| WARN this is accepted in the current edition //~| ERROR trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition let _x: &SomeTrait = todo!(); //~^ ERROR trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr index 931786672145b..65d44604dc9fc 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr @@ -30,7 +30,7 @@ LL | fn function(x: &SomeTrait, y: Box) { | +++ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:17:14 + --> $DIR/dyn-2018-edition-lint.rs:9:14 | LL | let _x: &SomeTrait = todo!(); | ^^^^^^^^^ @@ -42,61 +42,5 @@ help: use `dyn` LL | let _x: &dyn SomeTrait = todo!(); | +++ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:17 - | -LL | fn function(x: &SomeTrait, y: Box) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn function(x: &dyn SomeTrait, y: Box) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:17 - | -LL | fn function(x: &SomeTrait, y: Box) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn function(x: &dyn SomeTrait, y: Box) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:35 - | -LL | fn function(x: &SomeTrait, y: Box) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn function(x: &SomeTrait, y: Box) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:35 - | -LL | fn function(x: &SomeTrait, y: Box) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn function(x: &SomeTrait, y: Box) { - | +++ - -error: aborting due to 7 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs index 57d688492515b..e1aba8eda1bff 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs @@ -4,10 +4,6 @@ fn ice() -> impl AsRef { //~^ WARN trait objects without an explicit `dyn` are deprecated - //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! Foo } diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr index d3c2d5d5b9f8c..84aaedf183815 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr @@ -12,33 +12,5 @@ help: use `dyn` LL | fn ice() -> impl AsRef { | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 - | -LL | fn ice() -> impl AsRef { - | ^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn ice() -> impl AsRef { - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 - | -LL | fn ice() -> impl AsRef { - | ^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn ice() -> impl AsRef { - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs index 631a8cb2f08cc..9b1edba41aafe 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr index ecdc625015e4e..e9b7b248e612f 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr @@ -12,33 +12,5 @@ help: use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/cap-lints-allow.rs b/tests/ui/lint/force-warn/cap-lints-allow.rs index fdba7f4105e73..9609ea994312f 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.rs +++ b/tests/ui/lint/force-warn/cap-lints-allow.rs @@ -8,9 +8,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr index 5f5f2ff52b6d0..e569b2f9f1ae9 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.stderr +++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr @@ -12,33 +12,5 @@ help: use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/cap-lints-allow.rs:8:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/cap-lints-allow.rs:8:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs index 7ad7462ddc550..9736027452a8d 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs @@ -8,9 +8,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr index 3a0b1201b0cd8..c971e4d0d4d21 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr @@ -13,33 +13,5 @@ help: use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs index ee5a18c38292b..99cad614c25cd 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr index 92555eda2a737..97b8694984dd7 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr @@ -13,33 +13,5 @@ help: use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-lint-group.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-lint-group.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs index 248aece6fe77c..f0aacd773401f 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr index c14c7957a25f5..cd030cc1fcd18 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr @@ -13,33 +13,5 @@ help: use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/lint-stability-deprecated.rs b/tests/ui/lint/lint-stability-deprecated.rs index a56a37228e533..80bc85ff557fc 100644 --- a/tests/ui/lint/lint-stability-deprecated.rs +++ b/tests/ui/lint/lint-stability-deprecated.rs @@ -96,13 +96,10 @@ mod cross_crate { struct S1(T::TypeUnstable); struct S2(T::TypeDeprecated); //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text type A = dyn TraitWithAssociatedTypes< TypeUnstable = u8, TypeDeprecated = u16, //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` >; let _ = DeprecatedStruct { //~ WARN use of deprecated struct `lint_stability::DeprecatedStruct` diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr index 609fc56a8ae5f..51205ff434062 100644 --- a/tests/ui/lint/lint-stability-deprecated.stderr +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -77,241 +77,241 @@ LL | ... ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text - --> $DIR/lint-stability-deprecated.rs:108:17 + --> $DIR/lint-stability-deprecated.rs:105:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedUnstableStruct`: text - --> $DIR/lint-stability-deprecated.rs:111:17 + --> $DIR/lint-stability-deprecated.rs:108:17 | LL | let _ = DeprecatedUnstableStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `lint_stability::DeprecatedUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:118:17 + --> $DIR/lint-stability-deprecated.rs:115:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `lint_stability::DeprecatedUnstableUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:119:17 + --> $DIR/lint-stability-deprecated.rs:116:17 | LL | let _ = DeprecatedUnstableUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:123:23 + --> $DIR/lint-stability-deprecated.rs:120:23 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant`: text - --> $DIR/lint-stability-deprecated.rs:124:23 + --> $DIR/lint-stability-deprecated.rs:121:23 | LL | let _ = Enum::DeprecatedUnstableVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:128:17 + --> $DIR/lint-stability-deprecated.rs:125:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:129:17 + --> $DIR/lint-stability-deprecated.rs:126:17 | LL | let _ = DeprecatedUnstableTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:138:25 + --> $DIR/lint-stability-deprecated.rs:135:25 | LL | macro_test_arg!(deprecated_text()); | ^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:139:25 + --> $DIR/lint-stability-deprecated.rs:136:25 | LL | macro_test_arg!(deprecated_unstable_text()); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:140:41 + --> $DIR/lint-stability-deprecated.rs:137:41 | LL | macro_test_arg!(macro_test_arg!(deprecated_text())); | ^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:145:16 + --> $DIR/lint-stability-deprecated.rs:142:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:147:25 + --> $DIR/lint-stability-deprecated.rs:144:25 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:149:16 + --> $DIR/lint-stability-deprecated.rs:146:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:151:25 + --> $DIR/lint-stability-deprecated.rs:148:25 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:153:16 + --> $DIR/lint-stability-deprecated.rs:150:16 | LL | Trait::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:155:25 + --> $DIR/lint-stability-deprecated.rs:152:25 | LL | ... ::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:157:16 + --> $DIR/lint-stability-deprecated.rs:154:16 | LL | ... Trait::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:159:25 + --> $DIR/lint-stability-deprecated.rs:156:25 | LL | ... ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:187:10 + --> $DIR/lint-stability-deprecated.rs:184:10 | LL | impl DeprecatedTrait for S {} | ^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:189:25 + --> $DIR/lint-stability-deprecated.rs:186:25 | LL | trait LocalTrait2 : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:208:23 + --> $DIR/lint-stability-deprecated.rs:205:23 | LL | unstable_mod::deprecated(); | ^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:330:9 + --> $DIR/lint-stability-deprecated.rs:327:9 | LL | deprecated(); | ^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:335:16 + --> $DIR/lint-stability-deprecated.rs:332:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:337:25 + --> $DIR/lint-stability-deprecated.rs:334:25 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:339:9 + --> $DIR/lint-stability-deprecated.rs:336:9 | LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:344:16 + --> $DIR/lint-stability-deprecated.rs:341:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:346:25 + --> $DIR/lint-stability-deprecated.rs:343:25 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `this_crate::DeprecatedStruct`: text - --> $DIR/lint-stability-deprecated.rs:384:17 + --> $DIR/lint-stability-deprecated.rs:381:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:391:17 + --> $DIR/lint-stability-deprecated.rs:388:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:395:23 + --> $DIR/lint-stability-deprecated.rs:392:23 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:399:17 + --> $DIR/lint-stability-deprecated.rs:396:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:406:16 + --> $DIR/lint-stability-deprecated.rs:403:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:408:25 + --> $DIR/lint-stability-deprecated.rs:405:25 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:410:16 + --> $DIR/lint-stability-deprecated.rs:407:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:412:25 + --> $DIR/lint-stability-deprecated.rs:409:25 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text - --> $DIR/lint-stability-deprecated.rs:439:9 + --> $DIR/lint-stability-deprecated.rs:436:9 | LL | fn_in_body(); | ^^^^^^^^^^ warning: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:459:10 + --> $DIR/lint-stability-deprecated.rs:456:10 | LL | impl DeprecatedTrait for S { } | ^^^^^^^^^^^^^^^ warning: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:461:24 + --> $DIR/lint-stability-deprecated.rs:458:24 | LL | trait LocalTrait : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text - --> $DIR/lint-stability-deprecated.rs:447:13 + --> $DIR/lint-stability-deprecated.rs:444:13 | LL | fn_in_body(); | ^^^^^^^^^^ @@ -323,7 +323,7 @@ LL | struct S2(T::TypeDeprecated); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 + --> $DIR/lint-stability-deprecated.rs:101:13 | LL | TypeDeprecated = u16, | ^^^^^^^^^^^^^^^^^^^^ @@ -449,214 +449,190 @@ LL | ... ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated field `lint_stability::DeprecatedStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:109:13 + --> $DIR/lint-stability-deprecated.rs:106:13 | LL | i: 0 | ^^^^ warning: use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:113:13 + --> $DIR/lint-stability-deprecated.rs:110:13 | LL | i: 0 | ^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:144:13 + --> $DIR/lint-stability-deprecated.rs:141:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:146:16 + --> $DIR/lint-stability-deprecated.rs:143:16 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:148:13 + --> $DIR/lint-stability-deprecated.rs:145:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:150:16 + --> $DIR/lint-stability-deprecated.rs:147:16 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:152:13 + --> $DIR/lint-stability-deprecated.rs:149:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:154:16 + --> $DIR/lint-stability-deprecated.rs:151:16 | LL | ::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:156:13 + --> $DIR/lint-stability-deprecated.rs:153:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:158:16 + --> $DIR/lint-stability-deprecated.rs:155:16 | LL | ... ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:175:13 + --> $DIR/lint-stability-deprecated.rs:172:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:176:13 + --> $DIR/lint-stability-deprecated.rs:173:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:177:13 + --> $DIR/lint-stability-deprecated.rs:174:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:178:13 + --> $DIR/lint-stability-deprecated.rs:175:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:331:13 + --> $DIR/lint-stability-deprecated.rs:328:13 | LL | foo.method_deprecated(); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:332:14 + --> $DIR/lint-stability-deprecated.rs:329:14 | LL | Foo::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:333:16 + --> $DIR/lint-stability-deprecated.rs:330:16 | LL | ::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:334:13 + --> $DIR/lint-stability-deprecated.rs:331:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:336:16 + --> $DIR/lint-stability-deprecated.rs:333:16 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:340:13 + --> $DIR/lint-stability-deprecated.rs:337:13 | LL | foo.method_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:341:14 + --> $DIR/lint-stability-deprecated.rs:338:14 | LL | Foo::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:342:16 + --> $DIR/lint-stability-deprecated.rs:339:16 | LL | ::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:343:13 + --> $DIR/lint-stability-deprecated.rs:340:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:345:16 + --> $DIR/lint-stability-deprecated.rs:342:16 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated field `this_crate::DeprecatedStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:386:13 + --> $DIR/lint-stability-deprecated.rs:383:13 | LL | i: 0 | ^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:405:13 + --> $DIR/lint-stability-deprecated.rs:402:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:407:16 + --> $DIR/lint-stability-deprecated.rs:404:16 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:409:13 + --> $DIR/lint-stability-deprecated.rs:406:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:411:16 + --> $DIR/lint-stability-deprecated.rs:408:16 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:428:13 + --> $DIR/lint-stability-deprecated.rs:425:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:429:13 + --> $DIR/lint-stability-deprecated.rs:426:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:97:48 - | -LL | struct S2(T::TypeDeprecated); - | ^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 - | -LL | TypeDeprecated = u16, - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 - | -LL | TypeDeprecated = u16, - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 108 warnings emitted +warning: 105 warnings emitted diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs index 800624e3124b6..34daa81e48ea5 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs @@ -8,8 +8,6 @@ trait Foo { fn foo(_: &dyn Foo) {} //~^ WARN: unnecessary associated type bound for not object safe associated type -//~| WARN: unnecessary associated type bound for not object safe associated type -//~| WARN: unnecessary associated type bound for not object safe associated type #[allow(unused_associated_type_bounds)] fn bar(_: &dyn Foo) {} diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr index 659679e444095..f2bc8bd8400ce 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr @@ -7,23 +7,5 @@ LL | fn foo(_: &dyn Foo) {} = 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`. = note: `#[warn(unused_associated_type_bounds)]` on by default -warning: unnecessary associated type bound for not object safe associated type - --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 - | -LL | fn foo(_: &dyn Foo) {} - | ^^^^^^^^ help: remove this bound - | - = 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`. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unnecessary associated type bound for not object safe associated type - --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 - | -LL | fn foo(_: &dyn Foo) {} - | ^^^^^^^^ help: remove this bound - | - = 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`. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/privacy/associated-item-privacy-trait.stderr b/tests/ui/privacy/associated-item-privacy-trait.stderr index 4e9dfa4a83519..f79c4cff72fa2 100644 --- a/tests/ui/privacy/associated-item-privacy-trait.stderr +++ b/tests/ui/privacy/associated-item-privacy-trait.stderr @@ -75,17 +75,6 @@ LL | priv_trait::mac!(); | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:29:14 - | -LL | impl PrivTr for u8 {} - | ^^^^^^ private trait -... -LL | priv_trait::mac!(); - | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) - error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:46:21 | @@ -328,5 +317,16 @@ LL | priv_parent_substs::mac!(); | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-trait.rs:29:14 + | +LL | impl PrivTr for u8 {} + | ^^^^^^ private trait +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + error: aborting due to 30 previous errors diff --git a/tests/ui/privacy/associated-item-privacy-type-binding.stderr b/tests/ui/privacy/associated-item-privacy-type-binding.stderr index de9893816fade..52bfa3c2ab889 100644 --- a/tests/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/tests/ui/privacy/associated-item-privacy-type-binding.stderr @@ -32,10 +32,10 @@ LL | priv_trait::mac1!(); = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-type-binding.rs:16:31 + --> $DIR/associated-item-privacy-type-binding.rs:16:37 | LL | trait InSignatureTr2: PubTr {} - | ^^^^^^^^^^^^^^^^^^^ private trait + | ^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | ------------------- in this macro invocation @@ -164,10 +164,10 @@ LL | priv_parent_substs::mac!(); = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private - --> $DIR/associated-item-privacy-type-binding.rs:56:31 + --> $DIR/associated-item-privacy-type-binding.rs:56:37 | LL | trait InSignatureTr2: PubTr {} - | ^^^^^^^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation diff --git a/tests/ui/privacy/private-type-in-interface.stderr b/tests/ui/privacy/private-type-in-interface.stderr index a5e80d6962dba..091cae42dea3c 100644 --- a/tests/ui/privacy/private-type-in-interface.stderr +++ b/tests/ui/privacy/private-type-in-interface.stderr @@ -47,10 +47,10 @@ LL | fn g() -> impl Tr2 { 0 } | ^^^^^^^^^^^^^^^^^^ private type error: type `Priv` is private - --> $DIR/private-type-in-interface.rs:28:16 + --> $DIR/private-type-in-interface.rs:28:11 | LL | fn g() -> impl Tr2 { 0 } - | ^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^^^^^^^ private type error: type `ext::Priv` is private --> $DIR/private-type-in-interface.rs:30:15 @@ -59,10 +59,10 @@ LL | fn g_ext() -> impl Tr2 { 0 } | ^^^^^^^^^^^^^^^^^^^^ private type error: type `ext::Priv` is private - --> $DIR/private-type-in-interface.rs:30:20 + --> $DIR/private-type-in-interface.rs:30:15 | LL | fn g_ext() -> impl Tr2 { 0 } - | ^^^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^^^^^^^^^ private type error: aborting due to 11 previous errors diff --git a/tests/ui/privacy/struct-field-type.rs b/tests/ui/privacy/struct-field-type.rs new file mode 100644 index 0000000000000..6a4a19297e190 --- /dev/null +++ b/tests/ui/privacy/struct-field-type.rs @@ -0,0 +1,10 @@ +mod m { + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` +} + +struct S { + field: m::Leak, //~ ERROR: `Priv` is private +} + +fn main() {} diff --git a/tests/ui/privacy/struct-field-type.stderr b/tests/ui/privacy/struct-field-type.stderr new file mode 100644 index 0000000000000..854ff6a98a46b --- /dev/null +++ b/tests/ui/privacy/struct-field-type.stderr @@ -0,0 +1,21 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/struct-field-type.rs:3:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/struct-field-type.rs:2:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error: type `Priv` is private + --> $DIR/struct-field-type.rs:7:5 + | +LL | field: m::Leak, + | ^^^^^ private type + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/suggestions/issue-61963.rs b/tests/ui/suggestions/issue-61963.rs index a27c38452539c..d31ed01b1916b 100644 --- a/tests/ui/suggestions/issue-61963.rs +++ b/tests/ui/suggestions/issue-61963.rs @@ -18,20 +18,10 @@ pub struct Qux(T); pub struct Foo { //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition qux: Qux>, bar: Box, //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition } fn main() {} diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr index ec62153b0a76f..754d02b1c021b 100644 --- a/tests/ui/suggestions/issue-61963.stderr +++ b/tests/ui/suggestions/issue-61963.stderr @@ -1,5 +1,5 @@ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 + --> $DIR/issue-61963.rs:22:14 | LL | bar: Box, | ^^^ @@ -29,75 +29,5 @@ help: use `dyn` LL | dyn pub struct Foo { | +++ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 - | -LL | bar: Box, - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | bar: Box, - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 - | -LL | bar: Box, - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | bar: Box, - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: aborting due to 7 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs index acbf15dcb6c6a..5f3b711b31aa9 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs @@ -31,10 +31,7 @@ impl Tr for E { type V = u8; fn f() -> Self::V { 0 } //~^ ERROR ambiguous associated item - //~| ERROR ambiguous associated item //~| WARN this was previously accepted - //~| WARN this was previously accepted - //~| HELP use fully-qualified syntax //~| HELP use fully-qualified syntax } diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr index 359bd09ecd02b..0f42fcbe04d0a 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr @@ -18,25 +18,5 @@ LL | type V; | ^^^^^^ = note: `#[deny(ambiguous_associated_items)]` on by default -error: ambiguous associated item - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15 - | -LL | fn f() -> Self::V { 0 } - | ^^^^^^^ help: use fully-qualified syntax: `::V` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57644 -note: `V` could refer to the variant defined here - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5 - | -LL | V - | ^ -note: `V` could also refer to the associated type defined here - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5 - | -LL | type V; - | ^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error From af48cf63ee9b03801446ea9f14bdcba85b8035d5 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 7 Feb 2024 16:00:12 +0100 Subject: [PATCH 631/676] Don't use `assert_unsafe_precondition` twice. --- library/core/src/num/nonzero.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 8cbbc2aa1a24c..3d930c0831837 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -3,6 +3,7 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash::{Hash, Hasher}; +use crate::intrinsics; #[cfg(bootstrap)] use crate::marker::StructuralEq; use crate::marker::StructuralPartialEq; @@ -11,7 +12,6 @@ use crate::str::FromStr; use super::from_str_radix; use super::{IntErrorKind, ParseIntError}; -use crate::intrinsics; mod private { #[unstable( @@ -115,12 +115,11 @@ where None => { // SAFETY: The caller guarantees that `n` is non-zero, so this is unreachable. unsafe { - crate::intrinsics::assert_unsafe_precondition!( - "NonZero::new_unchecked requires the argument to be non-zero", - () => false + intrinsics::assert_unsafe_precondition!( + "NonZero::new_unchecked requires the argument to be non-zero", + () => false, ); - - crate::hint::unreachable_unchecked() + intrinsics::unreachable() } } } @@ -155,12 +154,11 @@ where None => { // SAFETY: The caller guarantees that `n` references a value that is non-zero, so this is unreachable. unsafe { - crate::intrinsics::assert_unsafe_precondition!( + intrinsics::assert_unsafe_precondition!( "NonZero::from_mut_unchecked requires the argument to dereference as non-zero", - () => false + () => false, ); - - crate::hint::unreachable_unchecked() + intrinsics::unreachable() } } } @@ -770,7 +768,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { fn div(self, other: $Ty) -> $Int { // SAFETY: div by zero is checked because `other` is a nonzero, // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_div(self, other.get()) } + unsafe { intrinsics::unchecked_div(self, other.get()) } } } @@ -783,7 +781,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { fn rem(self, other: $Ty) -> $Int { // SAFETY: rem by zero is checked because `other` is a nonzero, // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } + unsafe { intrinsics::unchecked_rem(self, other.get()) } } } }; From 5d65418e737584e303d70a49270326822bcd2a8f Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 7 Feb 2024 16:00:48 +0100 Subject: [PATCH 632/676] Replace `transmute_copy` with `ptr::read`. --- library/core/src/num/nonzero.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 3d930c0831837..193f2fa8731af 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -8,6 +8,7 @@ use crate::intrinsics; use crate::marker::StructuralEq; use crate::marker::StructuralPartialEq; use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem}; +use crate::ptr; use crate::str::FromStr; use super::from_str_radix; @@ -96,7 +97,7 @@ where pub const fn new(n: T) -> Option { // SAFETY: Memory layout optimization guarantees that `Option>` has // the same layout and size as `T`, with `0` representing `None`. - unsafe { crate::mem::transmute_copy(&n) } + unsafe { ptr::read(ptr::addr_of!(n).cast()) } } /// Creates a non-zero without checking whether the value is non-zero. From 42298756c740e217058c4fedebf2063192246ae0 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 6 Feb 2024 09:04:19 +0100 Subject: [PATCH 633/676] Update test output. --- tests/ui/print_type_sizes/niche-filling.rs | 4 ++-- tests/ui/print_type_sizes/niche-filling.stdout | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs index 5ee5085ddc8e1..feb9643850d05 100644 --- a/tests/ui/print_type_sizes/niche-filling.rs +++ b/tests/ui/print_type_sizes/niche-filling.rs @@ -1,5 +1,5 @@ -// compile-flags: -Z print-type-sizes --crate-type=lib -// ignore-debug debug assertions will print more types +// compile-flags: -Z print-type-sizes --crate-type lib +// ignore-debug: debug assertions will print more types // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout index b53b893660321..53a58ccc4eef8 100644 --- a/tests/ui/print_type_sizes/niche-filling.stdout +++ b/tests/ui/print_type_sizes/niche-filling.stdout @@ -70,6 +70,10 @@ print-type-size field `.a`: 4 bytes print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes print-type-size type: `std::num::NonZero`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes +print-type-size type: `std::option::Option>`: 4 bytes, alignment: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `Enum4<(), (), (), MyOption>`: 2 bytes, alignment: 1 bytes print-type-size variant `Four`: 2 bytes print-type-size field `.0`: 2 bytes From 5c25de67d49014397d5c09bcac5f2770b9fda1be Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 7 Feb 2024 15:03:31 +0000 Subject: [PATCH 634/676] Remove now-useless method override --- compiler/rustc_privacy/src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index eaec09cfbc234..6ebbb240d8400 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1128,13 +1128,6 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { intravisit::walk_inf(self, inf); } - fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) { - self.span = trait_ref.path.span; - // Privacy of traits in bodies is checked as a part of trait object types. - - intravisit::walk_trait_ref(self, trait_ref); - } - // Check types of expressions fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { if self.check_expr_pat_type(expr.hir_id, expr.span) { From 18e5bbfad6c6905704ac111f9fdffbbe638c8e33 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Tue, 6 Feb 2024 22:37:47 +0100 Subject: [PATCH 635/676] improve pretty printing for trait objects --- compiler/rustc_middle/src/traits/util.rs | 54 ++++++++++++-------- compiler/rustc_middle/src/ty/print/pretty.rs | 53 ++++++++++++++----- tests/ui/traits/object/pretty.stderr | 50 +++++++++--------- tests/ui/wf/hir-wf-canonicalized.rs | 4 +- tests/ui/wf/hir-wf-canonicalized.stderr | 8 +-- 5 files changed, 106 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index b4054f8ff5edd..fd5302dc75b13 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -1,46 +1,60 @@ use rustc_data_structures::fx::FxHashSet; -use crate::ty::{PolyTraitRef, TyCtxt}; +use crate::ty::{Clause, PolyTraitRef, ToPolyTraitRef, ToPredicate, TyCtxt}; -/// Given a PolyTraitRef, get the PolyTraitRefs of the trait's (transitive) supertraits. +/// Given a [`PolyTraitRef`], get the [`Clause`]s implied by the trait's definition. +/// /// This only exists in `rustc_middle` because the more powerful elaborator depends on /// `rustc_infer` for elaborating outlives bounds -- this should only be used for pretty /// printing. +pub fn super_predicates_for_pretty_printing<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: PolyTraitRef<'tcx>, +) -> impl Iterator> { + let clause = trait_ref.to_predicate(tcx); + Elaborator { tcx, visited: FxHashSet::from_iter([clause]), stack: vec![clause] } +} + +/// Like [`super_predicates_for_pretty_printing`], except it only returns traits and filters out +/// all other [`Clause`]s. pub fn supertraits_for_pretty_printing<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: PolyTraitRef<'tcx>, ) -> impl Iterator> { - Elaborator { tcx, visited: FxHashSet::from_iter([trait_ref]), stack: vec![trait_ref] } + super_predicates_for_pretty_printing(tcx, trait_ref).filter_map(|clause| { + clause.as_trait_clause().map(|trait_clause| trait_clause.to_poly_trait_ref()) + }) } struct Elaborator<'tcx> { tcx: TyCtxt<'tcx>, - visited: FxHashSet>, - stack: Vec>, + visited: FxHashSet>, + stack: Vec>, } impl<'tcx> Elaborator<'tcx> { fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) { - let supertrait_refs = self - .tcx - .super_predicates_of(trait_ref.def_id()) - .predicates - .into_iter() - .flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause()) - .map(|t| t.map_bound(|pred| pred.trait_ref)) - .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); - - self.stack.extend(supertrait_refs); + let super_predicates = + self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( + |&(pred, _)| { + let clause = pred.subst_supertrait(self.tcx, &trait_ref); + self.visited.insert(clause).then_some(clause) + }, + ); + + self.stack.extend(super_predicates); } } impl<'tcx> Iterator for Elaborator<'tcx> { - type Item = PolyTraitRef<'tcx>; + type Item = Clause<'tcx>; - fn next(&mut self) -> Option> { - if let Some(trait_ref) = self.stack.pop() { - self.elaborate(trait_ref); - Some(trait_ref) + fn next(&mut self) -> Option> { + if let Some(clause) = self.stack.pop() { + if let Some(trait_clause) = clause.as_trait_clause() { + self.elaborate(trait_clause.to_poly_trait_ref()); + } + Some(clause) } else { None } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index c0bfd2380ade0..fe009ccd47877 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,7 +1,7 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::query::IntoQueryParam; use crate::query::Providers; -use crate::traits::util::supertraits_for_pretty_printing; +use crate::traits::util::{super_predicates_for_pretty_printing, supertraits_for_pretty_printing}; use crate::ty::GenericArgKind; use crate::ty::{ ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable, @@ -1255,8 +1255,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // Generate the main trait ref, including associated types. let mut first = true; - if let Some(principal) = predicates.principal() { - self.wrap_binder(&principal, |principal, cx| { + if let Some(bound_principal) = predicates.principal() { + self.wrap_binder(&bound_principal, |principal, cx| { define_scoped_cx!(cx); p!(print_def_path(principal.def_id, &[])); @@ -1281,19 +1281,48 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`, // in order to place the projections inside the `<...>`. if !resugared { - // Use a type that can't appear in defaults of type parameters. - let dummy_cx = Ty::new_fresh(cx.tcx(), 0); - let principal = principal.with_self_ty(cx.tcx(), dummy_cx); + let principal_with_self = + principal.with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self); let args = cx .tcx() - .generics_of(principal.def_id) - .own_args_no_defaults(cx.tcx(), principal.args); + .generics_of(principal_with_self.def_id) + .own_args_no_defaults(cx.tcx(), principal_with_self.args); + + let bound_principal_with_self = bound_principal + .with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self); + + let super_projections: Vec<_> = + super_predicates_for_pretty_printing(cx.tcx(), bound_principal_with_self) + .filter_map(|clause| clause.as_projection_clause()) + .collect(); + + let mut projections: Vec<_> = predicates + .projection_bounds() + .filter_map(|proj| { + // Filter out projections that are implied by the super predicates. + let proj_is_implied = super_projections.iter().any(|&super_proj| { + let proj = cx.tcx().anonymize_bound_vars(proj); + let super_proj = cx.tcx().anonymize_bound_vars(super_proj); + assert_eq!(proj.bound_vars(), super_proj.bound_vars()); + + let proj = proj.skip_binder(); + let super_proj = ty::ExistentialProjection::erase_self_ty( + cx.tcx(), + super_proj.skip_binder(), + ); - let mut projections: Vec<_> = predicates.projection_bounds().collect(); - projections.sort_by_cached_key(|proj| { - cx.tcx().item_name(proj.item_def_id()).to_string() - }); + proj == super_proj + }); + + // Skip the binder, because we don't want to print the binder in + // front of the associated item. + (!proj_is_implied).then_some(proj.skip_binder()) + }) + .collect(); + + projections + .sort_by_cached_key(|proj| cx.tcx().item_name(proj.def_id).to_string()); if !args.is_empty() || !projections.is_empty() { p!(generic_delimiters(|cx| { diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr index 2fa87e7a6fe54..7658112476daf 100644 --- a/tests/ui/traits/object/pretty.stderr +++ b/tests/ui/traits/object/pretty.stderr @@ -24,34 +24,34 @@ error[E0308]: mismatched types --> $DIR/pretty.rs:20:31 | LL | fn dyn_fixed(x: &dyn Fixed) { x } - | - ^ expected `()`, found `&dyn Fixed` + | - ^ expected `()`, found `&dyn Fixed` | | - | help: try adding a return type: `-> &dyn Fixed` + | help: try adding a return type: `-> &dyn Fixed` | = note: expected unit type `()` - found reference `&dyn Fixed` + found reference `&dyn Fixed` error[E0308]: mismatched types --> $DIR/pretty.rs:21:50 | LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } - | - ^ expected `()`, found `&dyn Fixed` + | - ^ expected `()`, found `&dyn Fixed` | | - | help: try adding a return type: `-> &dyn Fixed` + | help: try adding a return type: `-> &dyn Fixed` | = note: expected unit type `()` - found reference `&dyn Fixed` + found reference `&dyn Fixed` error[E0308]: mismatched types --> $DIR/pretty.rs:22:38 | LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } - | - ^ expected `()`, found `&dyn FixedSub` + | - ^ expected `()`, found `&dyn FixedSub` | | - | help: try adding a return type: `-> &dyn FixedSub` + | help: try adding a return type: `-> &dyn FixedSub` | = note: expected unit type `()` - found reference `&dyn FixedSub` + found reference `&dyn FixedSub` error[E0308]: mismatched types --> $DIR/pretty.rs:24:74 @@ -59,10 +59,10 @@ error[E0308]: mismatched types LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>) { x } | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc = &u8>` | | - | help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, for<'a> Assoc = &'a u8>` + | help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>` | = note: expected unit type `()` - found reference `&dyn for<'a> SuperGeneric<'a, for<'a> Assoc = &'a u8>` + found reference `&dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>` error[E0308]: mismatched types --> $DIR/pretty.rs:25:70 @@ -70,54 +70,54 @@ error[E0308]: mismatched types LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>) { x } | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc = &u8>` | | - | help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, for<'a> Assoc = &'a u8>` + | help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>` | = note: expected unit type `()` - found reference `&dyn for<'a> AnyGeneric<'a, for<'a> Assoc = &'a u8>` + found reference `&dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>` error[E0308]: mismatched types --> $DIR/pretty.rs:26:60 | LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } - | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = &u8>` + | - ^ expected `()`, found `&dyn FixedGeneric1<'a>` | | - | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &'a u8>` + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a>` | = note: expected unit type `()` - found reference `&dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &'a u8>` + found reference `&dyn for<'a> FixedGeneric1<'a>` error[E0308]: mismatched types --> $DIR/pretty.rs:27:60 | LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } - | - ^ expected `()`, found `&dyn FixedGeneric2<'a, Assoc = &u8>` + | - ^ expected `()`, found `&dyn FixedGeneric2<'a>` | | - | help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a, for<'a> Assoc = &'a u8>` + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a>` | = note: expected unit type `()` - found reference `&dyn for<'a> FixedGeneric2<'a, for<'a> Assoc = &'a u8>` + found reference `&dyn for<'a> FixedGeneric2<'a>` error[E0308]: mismatched types --> $DIR/pretty.rs:28:78 | LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>) { x } - | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = ..., Assoc = ...>` + | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = &u8>` | | - | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &u8, for<'a> Assoc = &'a u8>` + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>` | = note: expected unit type `()` - found reference `&dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &u8, for<'a> Assoc = &'a u8>` + found reference `&dyn for<'a> FixedGeneric1<'a, Assoc = &u8>` error[E0308]: mismatched types --> $DIR/pretty.rs:29:40 | LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } - | - ^ expected `()`, found `&dyn FixedHrtb` + | - ^ expected `()`, found `&dyn FixedHrtb` | | - | help: try adding a return type: `-> &dyn FixedHrtb Assoc = &'a u8>` + | help: try adding a return type: `-> &dyn FixedHrtb` | = note: expected unit type `()` - found reference `&dyn FixedHrtb Assoc = &'a u8>` + found reference `&dyn FixedHrtb` error: aborting due to 11 previous errors diff --git a/tests/ui/wf/hir-wf-canonicalized.rs b/tests/ui/wf/hir-wf-canonicalized.rs index bdb84409d009d..eac238f0fcab1 100644 --- a/tests/ui/wf/hir-wf-canonicalized.rs +++ b/tests/ui/wf/hir-wf-canonicalized.rs @@ -9,8 +9,8 @@ trait Callback: Fn(&Bar<'_, T>, &T::V) {} struct Bar<'a, T> { callback: Box>>>, //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied - //~| ERROR the trait bound `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied - //~| ERROR the size for values of type `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time + //~| ERROR the trait bound `(dyn Callback, Output = ()> + 'static): Foo` is not satisfied + //~| ERROR the size for values of type `(dyn Callback, Output = ()> + 'static)` cannot be known at compilation time } impl Bar<'_, Bar<'_, T>> {} diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr index 4dca1f65232e2..8938801ce3d97 100644 --- a/tests/ui/wf/hir-wf-canonicalized.stderr +++ b/tests/ui/wf/hir-wf-canonicalized.stderr @@ -10,11 +10,11 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error[E0277]: the trait bound `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied +error[E0277]: the trait bound `(dyn Callback, Output = ()> + 'static): Foo` is not satisfied --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box>>>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback, Output = ()> + 'static)` | help: this trait has no implementations, consider adding one --> $DIR/hir-wf-canonicalized.rs:3:1 @@ -22,13 +22,13 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error[E0277]: the size for values of type `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time +error[E0277]: the size for values of type `(dyn Callback, Output = ()> + 'static)` cannot be known at compilation time --> $DIR/hir-wf-canonicalized.rs:10:15 | 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)` + = help: the trait `Sized` is not implemented for `(dyn Callback, Output = ()> + 'static)` note: required by an implicit `Sized` bound in `Bar` --> $DIR/hir-wf-canonicalized.rs:9:16 | From e867886c6ac20e7b7d8fb4aefcd02490ac7fc80b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 7 Feb 2024 15:26:07 +0000 Subject: [PATCH 636/676] Remove dead code --- compiler/rustc_privacy/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 6ebbb240d8400..6fdf4b506ea69 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -98,9 +98,6 @@ trait DefIdVisitor<'tcx> { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow { self.skeleton().visit_trait(trait_ref) } - fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow { - self.skeleton().visit_projection_ty(projection) - } fn visit_predicates( &mut self, predicates: ty::GenericPredicates<'tcx>, From dcca9a12cdda3be34ed74beca05d72c77d797e7f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Feb 2024 16:06:52 +0000 Subject: [PATCH 637/676] Record coroutine kind in generics --- .../src/collect/generics_of.rs | 13 ++++++++++--- compiler/rustc_middle/src/ty/instance.rs | 9 ++++++++- tests/ui/coroutine/polymorphize-args.rs | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 tests/ui/coroutine/polymorphize-args.rs diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 1dabb6feb5e1b..4860555de2056 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -344,11 +344,18 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { kind: hir::ExprKind::Closure(hir::Closure { kind, .. }), .. }) = node { + // See `ClosureArgsParts`, `CoroutineArgsParts`, and `CoroutineClosureArgsParts` + // for info on the usage of each of these fields. let dummy_args = match kind { ClosureKind::Closure => &["", "", ""][..], - ClosureKind::Coroutine(_) => { - &["", "", "", "", ""][..] - } + ClosureKind::Coroutine(_) => &[ + "", + "", + "", + "", + "", + "", + ][..], ClosureKind::CoroutineClosure(_) => &[ "", "", diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 9c1f4b20d2c83..8848d216f5b49 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -765,7 +765,14 @@ fn polymorphize<'tcx>( let def_id = instance.def_id(); let upvars_ty = match tcx.type_of(def_id).skip_binder().kind() { ty::Closure(..) => Some(args.as_closure().tupled_upvars_ty()), - ty::Coroutine(..) => Some(args.as_coroutine().tupled_upvars_ty()), + ty::Coroutine(..) => { + assert_eq!( + args.as_coroutine().kind_ty(), + tcx.types.unit, + "polymorphization does not support coroutines from async closures" + ); + Some(args.as_coroutine().tupled_upvars_ty()) + } _ => None, }; let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty()); diff --git a/tests/ui/coroutine/polymorphize-args.rs b/tests/ui/coroutine/polymorphize-args.rs new file mode 100644 index 0000000000000..de44d667656c4 --- /dev/null +++ b/tests/ui/coroutine/polymorphize-args.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zpolymorphize=on +// build-pass + +#![feature(coroutines, coroutine_trait)] + +use std::ops::Coroutine; +use std::pin::Pin; +use std::thread; + +fn main() { + let mut foo = || yield; + thread::spawn(move || match Pin::new(&mut foo).resume(()) { + s => panic!("bad state: {:?}", s), + }) + .join() + .unwrap(); +} From a41ceff982aa81fbb0e17ae3f923e48fad4b6be0 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 7 Feb 2024 12:03:12 -0500 Subject: [PATCH 638/676] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index cdf84b69d0416..ccc84ccec4b73 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit cdf84b69d0416c57ac9dc3459af80dfb4883d27a +Subproject commit ccc84ccec4b7340eb916aefda1cb3e2fe17d8e7b From cd21b1d036fbc1f8e72451442feb12b098c33ef5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Feb 2024 19:27:44 +0000 Subject: [PATCH 639/676] No need to take ImplTraitContext by ref --- compiler/rustc_ast_lowering/src/asm.rs | 2 +- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_lowering/src/delegation.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 18 ++--- compiler/rustc_ast_lowering/src/item.rs | 80 +++++++++---------- compiler/rustc_ast_lowering/src/lib.rs | 56 ++++++------- compiler/rustc_ast_lowering/src/pat.rs | 6 +- compiler/rustc_ast_lowering/src/path.rs | 16 ++-- 8 files changed, 90 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 3742cf9d881d8..fd717e82d26df 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -205,7 +205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.qself, &sym.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); hir::InlineAsmOperand::SymStatic { path, def_id } diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index d310f72f7a3f8..865a56b2c1f15 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -85,7 +85,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = l .ty .as_ref() - .map(|t| self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 6ccf39b0cb167..d1ba93f067553 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -218,7 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &delegation.qself, &delegation.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let block = delegation.body.as_deref(); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c4798887637f8..942aae3d53600 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -99,7 +99,7 @@ impl<'hir> LoweringContext<'_, 'hir> { seg, ParamMode::Optional, ParenthesizedGenericArgs::Err, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, // Method calls can't have bound modifiers None, @@ -141,13 +141,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Cast(expr, ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(expr, ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ohs) => { @@ -267,7 +267,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); hir::ExprKind::Path(qpath) @@ -295,7 +295,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf( self.lower_ty( container, - &ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), + ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), ), self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))), ), @@ -314,7 +314,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, )), self.arena @@ -1241,7 +1241,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); // Destructure like a tuple struct. @@ -1261,7 +1261,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); // Destructure like a unit struct. @@ -1286,7 +1286,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let fields_omitted = match &se.rest { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7b81ed4875c64..75410323f97df 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -189,7 +189,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy) }, @@ -218,7 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, decl) = - this.lower_generics(generics, header.constness, id, &itctx, |this| { + this.lower_generics(generics, header.constness, id, itctx, |this| { this.lower_fn_decl( decl, id, @@ -263,7 +263,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let guar = this.dcx().span_delayed_bug( @@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } Some(ty) => this.lower_ty( ty, - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, ), }, ); @@ -285,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.arena.alloc_from_iter( enum_definition.variants.iter().map(|x| this.lower_variant(x)), @@ -299,7 +299,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); hir::ItemKind::Struct(struct_def, generics) @@ -309,7 +309,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); hir::ItemKind::Union(vdata, generics) @@ -339,7 +339,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // parent lifetime. let itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, *constness, id, &itctx, |this| { + self.lower_generics(ast_generics, *constness, id, itctx, |this| { let modifiers = TraitBoundModifiers { constness: match *constness { Const::Yes(span) => BoundConstness::Maybe(span), @@ -354,13 +354,13 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_trait_ref( modifiers, trait_ref, - &ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) }); let lowered_ty = this.lower_ty( ty, - &ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf), + ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf), ); (trait_ref, lowered_ty) @@ -400,11 +400,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, constness, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let bounds = this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -420,11 +420,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, ); @@ -464,7 +464,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body: Option<&Expr>, impl_trait_position: ImplTraitPosition, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(impl_trait_position)); + let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position)); (ty, self.lower_const_body(span, body)) } @@ -633,7 +633,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, Const::No, i.id, &itctx, |this| { + self.lower_generics(generics, Const::No, i.id, itctx, |this| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl( @@ -650,8 +650,8 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(t, m, _) => { - let ty = self - .lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); + let ty = + self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); hir::ForeignItemKind::Static(ty, *m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -722,11 +722,11 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), + ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) + self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -755,12 +755,10 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { - let ty = this.lower_ty( - ty, - &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), - ); + let ty = this + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x))); hir::TraitItemKind::Const(ty, body) @@ -803,18 +801,18 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { this.lower_ty( x, - &ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy), + ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy), ) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, ) @@ -882,10 +880,10 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { - let ty = this - .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); + let ty = + this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = this.lower_const_body(i.span, expr.as_deref()); hir::ImplItemKind::Const(ty, body) @@ -916,7 +914,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let guar = this.dcx().span_delayed_bug( @@ -929,7 +927,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(ty) => { let ty = this.lower_ty( ty, - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, ); hir::ImplItemKind::Type(ty) } @@ -1323,7 +1321,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // synthesize a host effect param for them. We reject `const` on them during AST validation. let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No }; let itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, constness, id, &itctx, |this| { + let (generics, decl) = self.lower_generics(generics, constness, id, itctx, |this| { this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) @@ -1401,7 +1399,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics: &Generics, constness: Const, parent_node_id: NodeId, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, f: impl FnOnce(&mut Self) -> T, ) -> (&'hir hir::Generics<'hir>, T) { debug_assert!(self.impl_trait_defs.is_empty()); @@ -1607,7 +1605,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounds: &[GenericBound], colon_span: Option, parent_span: Span, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, origin: PredicateOrigin, ) -> Option> { // Do not create a clause if we do not have anything inside it. @@ -1681,10 +1679,10 @@ impl<'hir> LoweringContext<'_, 'hir> { bound_generic_params: self .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), bounded_ty: self - .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), bounds: self.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), span: self.lower_span(*span), origin: PredicateOrigin::WhereClause, @@ -1695,7 +1693,7 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime: self.lower_lifetime(lifetime), bounds: self.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, }) @@ -1703,9 +1701,9 @@ impl<'hir> LoweringContext<'_, 'hir> { WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty: self - .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), rhs_ty: self - .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), span: self.lower_span(*span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 063b6627050bc..b289f615d27bd 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1006,7 +1006,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint( &mut self, constraint: &AssocConstraint, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint @@ -1085,9 +1085,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBindingKind::Equality { term } } AssocConstraintKind::Bound { bounds } => { - enum DesugarKind<'a> { + enum DesugarKind { ImplTrait, - Error(&'a ImplTraitPosition), + Error(ImplTraitPosition), Bound, } @@ -1163,7 +1163,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { DesugarKind::Error(position) => { let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding { span: constraint.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }); let err_ty = &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); @@ -1210,7 +1210,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_arg( &mut self, arg: &ast::GenericArg, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)), @@ -1289,7 +1289,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: &ImplTraitContext) -> &'hir hir::Ty<'hir> { + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { self.arena.alloc(self.lower_ty_direct(t, itctx)) } @@ -1299,7 +1299,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option>, path: &Path, param_mode: ParamMode, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in @@ -1341,7 +1341,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> { + fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => { @@ -1460,13 +1460,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::ReturnPositionOpaqueTy { origin, fn_kind } => self .lower_opaque_impl_trait( span, - *origin, + origin, *def_node_id, bounds, - Some(*fn_kind), + Some(fn_kind), itctx, ), - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self .lower_opaque_impl_trait( span, hir::OpaqueTyOrigin::TyAlias { in_assoc_ty }, @@ -1513,9 +1513,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .create_feature_err( MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }, - *feature, + feature, ) .emit(); hir::TyKind::Err(guar) @@ -1523,7 +1523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(position) => { let guar = self.dcx().emit_err(MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }); hir::TyKind::Err(guar) } @@ -1581,7 +1581,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { opaque_ty_node_id: NodeId, bounds: &GenericBounds, fn_kind: Option, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1848,7 +1848,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam) } }; - self.lower_ty_direct(¶m.ty, &itctx) + self.lower_ty_direct(¶m.ty, itctx) })); let output = match coro { @@ -1876,7 +1876,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::PointerReturn) } }; - hir::FnRetTy::Return(self.lower_ty(ty, &itctx)) + hir::FnRetTy::Return(self.lower_ty(ty, itctx)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), }, @@ -1977,7 +1977,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output: &FnRetTy, coro: CoroutineKind, opaque_ty_span: Span, - nested_impl_trait_context: ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. let output_ty = match output { @@ -1985,7 +1985,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - self.lower_ty(ty, &nested_impl_trait_context) + self.lower_ty(ty, itctx) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -2025,7 +2025,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait( @@ -2164,7 +2164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .map(|def| { self.lower_ty( def, - &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), + ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), ) }); @@ -2174,7 +2174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } GenericParamKind::Const { ty, kw_span: _, default } => { let ty = self - .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); // Not only do we deny const param defaults in binders but we also map them to `None` // since later compiler stages cannot handle them (and shouldn't need to be able to). @@ -2204,7 +2204,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, modifiers: ast::TraitBoundModifiers, p: &TraitRef, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TraitRef<'hir> { let path = match self.lower_qpath( p.ref_id, @@ -2224,7 +2224,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, modifiers: ast::TraitBoundModifiers, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = @@ -2233,7 +2233,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } - fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> { + fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } @@ -2241,7 +2241,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds( &mut self, bounds: &[GenericBound], - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBounds<'hir> { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } @@ -2249,7 +2249,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds_mut<'s>( &'s mut self, bounds: &'s [GenericBound], - itctx: &'s ImplTraitContext, + itctx: ImplTraitContext, ) -> impl Iterator> + Captures<'s> + Captures<'a> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } @@ -2285,7 +2285,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds, /* colon_span */ None, span, - &ImplTraitContext::Universal, + ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 0af141ff99a27..c097feb6b3476 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -38,7 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); @@ -55,7 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); break hir::PatKind::Path(qpath); @@ -66,7 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 76c7e530a6bb7..48941a232c266 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -27,7 +27,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option>, p: &Path, param_mode: ParamMode, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, // modifiers of the impl/bound if this is a trait path modifiers: Option, ) -> hir::QPath<'hir> { @@ -205,7 +205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, None, ) @@ -220,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment: &PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, constness: Option, // Additional features ungated with a bound modifier like `async`. // This is passed down to the implicit associated type binding in @@ -374,7 +374,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { let has_non_lt_args = data.args.iter().any(|arg| match arg { AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) @@ -405,7 +405,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_parenthesized_parameter_data( &mut self, data: &ParenthesizedArgs, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, bound_modifier_allowed_features: Option>, ) -> (GenericArgsCtor<'hir>, bool) { // Switch to `PassThrough` mode for anonymous lifetimes; this @@ -415,7 +415,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) + self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) })); let output_ty = match output { // Only allow `impl Trait` in return position. i.e.: @@ -429,7 +429,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.lower_ty( ty, - &ImplTraitContext::FeatureGated( + ImplTraitContext::FeatureGated( ImplTraitPosition::FnTraitReturn, sym::impl_trait_in_fn_trait_return, ), @@ -437,7 +437,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } FnRetTy::Ty(ty) => { - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; From c636c7ae2cbdf576aa920359f687b9f0716a9418 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Wed, 7 Feb 2024 20:58:05 +0100 Subject: [PATCH 640/676] address review comments and add more tests --- compiler/rustc_middle/src/ty/print/pretty.rs | 25 +++--- tests/ui/traits/object/pretty.rs | 18 ++-- tests/ui/traits/object/pretty.stderr | 87 ++++++++++++++------ 3 files changed, 87 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fe009ccd47877..f90703e61844e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1299,25 +1299,30 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let mut projections: Vec<_> = predicates .projection_bounds() - .filter_map(|proj| { + .filter(|&proj| { // Filter out projections that are implied by the super predicates. let proj_is_implied = super_projections.iter().any(|&super_proj| { + let super_proj = super_proj.map_bound(|super_proj| { + ty::ExistentialProjection::erase_self_ty(cx.tcx(), super_proj) + }); + + // This function is sometimes called on types with erased and + // anonymized regions, but the super projections can still + // contain named regions. So we erase and anonymize everything + // here to compare the types modulo regions below. + let proj = cx.tcx().erase_regions(proj); let proj = cx.tcx().anonymize_bound_vars(proj); + let super_proj = cx.tcx().erase_regions(super_proj); let super_proj = cx.tcx().anonymize_bound_vars(super_proj); - assert_eq!(proj.bound_vars(), super_proj.bound_vars()); - - let proj = proj.skip_binder(); - let super_proj = ty::ExistentialProjection::erase_self_ty( - cx.tcx(), - super_proj.skip_binder(), - ); proj == super_proj }); - + !proj_is_implied + }) + .map(|proj| { // Skip the binder, because we don't want to print the binder in // front of the associated item. - (!proj_is_implied).then_some(proj.skip_binder()) + proj.skip_binder() }) .collect(); diff --git a/tests/ui/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs index 625c651d5f75a..8958871ed5d72 100644 --- a/tests/ui/traits/object/pretty.rs +++ b/tests/ui/traits/object/pretty.rs @@ -6,26 +6,32 @@ trait Super { trait Any: Super {} trait Fixed: Super {} trait FixedSub: Fixed {} +trait FixedStatic: Super {} trait SuperGeneric<'a> { - type Assoc; + type Assoc2; } trait AnyGeneric<'a>: SuperGeneric<'a> {} -trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc = &'a u8> {} +trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc2 = &'a u8> {} trait FixedGeneric2<'a>: Super {} -trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc = &'a u8> {} +trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {} +trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {} +trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {} fn dyn_super(x: &dyn Super) { x } //~ERROR mismatched types fn dyn_any(x: &dyn Any) { x } //~ERROR mismatched types fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types fn dyn_fixed_multi(x: &dyn Fixed) { x } //~ERROR mismatched types fn dyn_fixed_sub(x: &dyn FixedSub) { x } //~ERROR mismatched types +fn dyn_fixed_static(x: &dyn FixedStatic) { x } //~ERROR mismatched types -fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>) { x } //~ERROR mismatched types -fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>) { x } //~ERROR mismatched types +fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types +fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } //~ERROR mismatched types fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } //~ERROR mismatched types -fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>) { x } //~ERROR mismatched types +fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } //~ERROR mismatched types fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types +fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } //~ERROR mismatched types +fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } //~ERROR mismatched types fn main() {} diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr index 7658112476daf..bc645e5f9677d 100644 --- a/tests/ui/traits/object/pretty.stderr +++ b/tests/ui/traits/object/pretty.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/pretty.rs:18:43 + --> $DIR/pretty.rs:21:43 | LL | fn dyn_super(x: &dyn Super) { x } | - ^ expected `()`, found `&dyn Super` @@ -10,7 +10,7 @@ LL | fn dyn_super(x: &dyn Super) { x } found reference `&dyn Super` error[E0308]: mismatched types - --> $DIR/pretty.rs:19:39 + --> $DIR/pretty.rs:22:39 | LL | fn dyn_any(x: &dyn Any) { x } | - ^ expected `()`, found `&dyn Any` @@ -21,7 +21,7 @@ LL | fn dyn_any(x: &dyn Any) { x } found reference `&dyn Any` error[E0308]: mismatched types - --> $DIR/pretty.rs:20:31 + --> $DIR/pretty.rs:23:31 | LL | fn dyn_fixed(x: &dyn Fixed) { x } | - ^ expected `()`, found `&dyn Fixed` @@ -32,7 +32,7 @@ LL | fn dyn_fixed(x: &dyn Fixed) { x } found reference `&dyn Fixed` error[E0308]: mismatched types - --> $DIR/pretty.rs:21:50 + --> $DIR/pretty.rs:24:50 | LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } | - ^ expected `()`, found `&dyn Fixed` @@ -43,7 +43,7 @@ LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } found reference `&dyn Fixed` error[E0308]: mismatched types - --> $DIR/pretty.rs:22:38 + --> $DIR/pretty.rs:25:38 | LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } | - ^ expected `()`, found `&dyn FixedSub` @@ -54,29 +54,40 @@ LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } found reference `&dyn FixedSub` error[E0308]: mismatched types - --> $DIR/pretty.rs:24:74 + --> $DIR/pretty.rs:26:44 | -LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>) { x } - | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc = &u8>` - | | - | help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>` +LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } + | - ^ expected `()`, found `&dyn FixedStatic` + | | + | help: try adding a return type: `-> &dyn FixedStatic` | = note: expected unit type `()` - found reference `&dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>` + found reference `&dyn FixedStatic` error[E0308]: mismatched types - --> $DIR/pretty.rs:25:70 + --> $DIR/pretty.rs:28:75 | -LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>) { x } - | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc = &u8>` - | | - | help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>` +LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } + | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc2 = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` | = note: expected unit type `()` - found reference `&dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>` + found reference `&dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:26:60 + --> $DIR/pretty.rs:29:71 + | +LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } + | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc2 = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:30:60 | LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } | - ^ expected `()`, found `&dyn FixedGeneric1<'a>` @@ -87,7 +98,7 @@ LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } found reference `&dyn for<'a> FixedGeneric1<'a>` error[E0308]: mismatched types - --> $DIR/pretty.rs:27:60 + --> $DIR/pretty.rs:31:60 | LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } | - ^ expected `()`, found `&dyn FixedGeneric2<'a>` @@ -98,18 +109,18 @@ LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } found reference `&dyn for<'a> FixedGeneric2<'a>` error[E0308]: mismatched types - --> $DIR/pretty.rs:28:78 + --> $DIR/pretty.rs:32:79 | -LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>) { x } - | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = &u8>` - | | - | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>` +LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` | = note: expected unit type `()` - found reference `&dyn for<'a> FixedGeneric1<'a, Assoc = &u8>` + found reference `&dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:29:40 + --> $DIR/pretty.rs:33:40 | LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } | - ^ expected `()`, found `&dyn FixedHrtb` @@ -119,6 +130,28 @@ LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } = note: expected unit type `()` found reference `&dyn FixedHrtb` -error: aborting due to 11 previous errors +error[E0308]: mismatched types + --> $DIR/pretty.rs:34:73 + | +LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } + | - ^ expected `()`, found `&dyn AnyDifferentBinders` + | | + | help: try adding a return type: `-> &dyn AnyDifferentBinders` + | + = note: expected unit type `()` + found reference `&dyn AnyDifferentBinders` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:35:65 + | +LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } + | - ^ expected `()`, found `&dyn FixedDifferentBinders` + | | + | help: try adding a return type: `-> &dyn FixedDifferentBinders` + | + = note: expected unit type `()` + found reference `&dyn FixedDifferentBinders` + +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0308`. From 970f46c60de420205044c53092d6cff8200354d5 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 7 Feb 2024 04:12:52 +0100 Subject: [PATCH 641/676] Add tests --- .../empty-match.exhaustive_patterns.stderr | 101 +++++++++++++++--- .../usefulness/empty-match.normal.stderr | 101 +++++++++++++++--- tests/ui/pattern/usefulness/empty-match.rs | 6 ++ 3 files changed, 176 insertions(+), 32 deletions(-) diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index 9c3bebd7797b8..bf758999661e6 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -7,9 +7,36 @@ LL | match_no_arms!(0u8); = note: the matched value is of type `u8` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty +error[E0004]: non-exhaustive patterns: type `i8` is non-empty --> $DIR/empty-match.rs:47:20 | +LL | match_no_arms!(0i8); + | ^^^ + | + = note: the matched value is of type `i8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/empty-match.rs:48:20 + | +LL | match_no_arms!(0usize); + | ^^^^^^ + | + = note: the matched value is of type `usize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `isize` is non-empty + --> $DIR/empty-match.rs:49:20 + | +LL | match_no_arms!(0isize); + | ^^^^^^ + | + = note: the matched value is of type `isize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:50:20 + | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ | @@ -22,7 +49,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:48:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +63,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:49:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +77,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:50:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +91,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:51:20 + --> $DIR/empty-match.rs:54:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -80,7 +107,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:52:20 + --> $DIR/empty-match.rs:55:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -98,7 +125,7 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:53:20 + --> $DIR/empty-match.rs:56:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -122,7 +149,7 @@ LL | V5, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:55:24 + --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `_` not covered @@ -135,8 +162,50 @@ LL ~ _ if false => {}, LL + _ => todo!() | +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:59:24 + | +LL | match_guarded_arm!(0i8); + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `i8` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:60:24 + | +LL | match_guarded_arm!(0usize); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:61:24 + | +LL | match_guarded_arm!(0isize); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + _ => todo!() + | + error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:56:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -155,7 +224,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:57:24 + --> $DIR/empty-match.rs:63:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -174,7 +243,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:58:24 + --> $DIR/empty-match.rs:64:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -193,7 +262,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:59:24 + --> $DIR/empty-match.rs:65:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -212,7 +281,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:60:24 + --> $DIR/empty-match.rs:66:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -233,7 +302,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:61:24 + --> $DIR/empty-match.rs:67:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -256,7 +325,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:62:24 + --> $DIR/empty-match.rs:68:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -284,6 +353,6 @@ LL ~ _ if false => {}, LL + _ => todo!() | -error: aborting due to 16 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index 9c3bebd7797b8..bf758999661e6 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -7,9 +7,36 @@ LL | match_no_arms!(0u8); = note: the matched value is of type `u8` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty +error[E0004]: non-exhaustive patterns: type `i8` is non-empty --> $DIR/empty-match.rs:47:20 | +LL | match_no_arms!(0i8); + | ^^^ + | + = note: the matched value is of type `i8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/empty-match.rs:48:20 + | +LL | match_no_arms!(0usize); + | ^^^^^^ + | + = note: the matched value is of type `usize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `isize` is non-empty + --> $DIR/empty-match.rs:49:20 + | +LL | match_no_arms!(0isize); + | ^^^^^^ + | + = note: the matched value is of type `isize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:50:20 + | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ | @@ -22,7 +49,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:48:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +63,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:49:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +77,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:50:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +91,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:51:20 + --> $DIR/empty-match.rs:54:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -80,7 +107,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:52:20 + --> $DIR/empty-match.rs:55:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -98,7 +125,7 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:53:20 + --> $DIR/empty-match.rs:56:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -122,7 +149,7 @@ LL | V5, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:55:24 + --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `_` not covered @@ -135,8 +162,50 @@ LL ~ _ if false => {}, LL + _ => todo!() | +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:59:24 + | +LL | match_guarded_arm!(0i8); + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `i8` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:60:24 + | +LL | match_guarded_arm!(0usize); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:61:24 + | +LL | match_guarded_arm!(0isize); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + _ => todo!() + | + error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:56:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -155,7 +224,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:57:24 + --> $DIR/empty-match.rs:63:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -174,7 +243,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:58:24 + --> $DIR/empty-match.rs:64:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -193,7 +262,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:59:24 + --> $DIR/empty-match.rs:65:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -212,7 +281,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:60:24 + --> $DIR/empty-match.rs:66:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -233,7 +302,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:61:24 + --> $DIR/empty-match.rs:67:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -256,7 +325,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:62:24 + --> $DIR/empty-match.rs:68:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -284,6 +353,6 @@ LL ~ _ if false => {}, LL + _ => todo!() | -error: aborting due to 16 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index 321f24adc46b4..ff9e488ceaf77 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -44,6 +44,9 @@ fn nonempty() { } match_no_arms!(0u8); //~ ERROR type `u8` is non-empty + match_no_arms!(0i8); //~ ERROR type `i8` is non-empty + match_no_arms!(0usize); //~ ERROR type `usize` is non-empty + match_no_arms!(0isize); //~ ERROR type `isize` is non-empty match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty @@ -53,6 +56,9 @@ fn nonempty() { match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered match_guarded_arm!(0u8); //~ ERROR `_` not covered + match_guarded_arm!(0i8); //~ ERROR `_` not covered + match_guarded_arm!(0usize); //~ ERROR `_` not covered + match_guarded_arm!(0isize); //~ ERROR `_` not covered match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered From 9dca6be7b83f4816f67ebaa11008348ce022eb60 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 7 Feb 2024 04:00:02 +0100 Subject: [PATCH 642/676] Prefer "0..MAX not covered" to "_ not covered" --- .../rustc_pattern_analysis/src/usefulness.rs | 8 +++----- ...atch-check-notes.exhaustive_patterns.stderr | 6 +++--- .../empty-match-check-notes.normal.stderr | 6 +++--- .../usefulness/empty-match-check-notes.rs | 4 ++-- .../empty-match.exhaustive_patterns.stderr | 18 +++++++++--------- .../usefulness/empty-match.normal.stderr | 18 +++++++++--------- tests/ui/pattern/usefulness/empty-match.rs | 6 +++--- 7 files changed, 32 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 576005b2c7f8f..80a807b4f2759 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1520,11 +1520,9 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( split_ctors.push(Constructor::Missing); } - // Decide what constructors to report. - let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); - let always_report_all = place.is_scrutinee && !is_integers; - // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". - let report_individual_missing_ctors = always_report_all || !all_missing; + // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". At the top + // level we prefer to list all constructors. + let report_individual_missing_ctors = place.is_scrutinee || !all_missing; // Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() => // split_ctors.contains(Missing)`. The converse usually holds except when // `!place_validity.is_known_valid()`. diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index 304435cb21e8a..4c43419243190 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -43,18 +43,18 @@ help: you might want to use `if let` to ignore the variant that isn't matched LL | if let None = x { todo!() }; | ++ +++++++++++ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered --> $DIR/empty-match-check-notes.rs:45:11 | LL | match 0u8 { - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_u8..=u8::MAX => todo!() | error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr index 40494b726f00c..45f715dc7b2dc 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -42,18 +42,18 @@ help: you might want to use `if let` to ignore the variant that isn't matched LL | if let None = x { todo!() }; | ++ +++++++++++ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered --> $DIR/empty-match-check-notes.rs:45:11 | LL | match 0u8 { - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_u8..=u8::MAX => todo!() | error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs index ee9ff3dcf9012..c30cdfc2e4fee 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.rs +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs @@ -43,10 +43,10 @@ fn empty_foreign_enum_private(x: Option fn main() { match 0u8 { - //~^ ERROR `_` not covered + //~^ ERROR not covered //~| NOTE the matched value is of type //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE pattern `_` not covered + //~| NOTE not covered _ if false => {} } } diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index bf758999661e6..5f895fab0fba4 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -148,46 +148,46 @@ LL | V5, = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!(0u8); - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_u8..=u8::MAX => todo!() | -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered --> $DIR/empty-match.rs:59:24 | LL | match_guarded_arm!(0i8); - | ^^^ pattern `_` not covered + | ^^^ pattern `i8::MIN..=i8::MAX` not covered | = note: the matched value is of type `i8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + i8::MIN..=i8::MAX => todo!() | -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_usize..` not covered --> $DIR/empty-match.rs:60:24 | LL | match_guarded_arm!(0usize); - | ^^^^^^ pattern `_` not covered + | ^^^^^^ pattern `0_usize..` not covered | = note: the matched value is of type `usize` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_usize.. => todo!() | error[E0004]: non-exhaustive patterns: `_` not covered diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index bf758999661e6..5f895fab0fba4 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -148,46 +148,46 @@ LL | V5, = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!(0u8); - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_u8..=u8::MAX => todo!() | -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered --> $DIR/empty-match.rs:59:24 | LL | match_guarded_arm!(0i8); - | ^^^ pattern `_` not covered + | ^^^ pattern `i8::MIN..=i8::MAX` not covered | = note: the matched value is of type `i8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + i8::MIN..=i8::MAX => todo!() | -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_usize..` not covered --> $DIR/empty-match.rs:60:24 | LL | match_guarded_arm!(0usize); - | ^^^^^^ pattern `_` not covered + | ^^^^^^ pattern `0_usize..` not covered | = note: the matched value is of type `usize` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_usize.. => todo!() | error[E0004]: non-exhaustive patterns: `_` not covered diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index ff9e488ceaf77..20ab702c9c899 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -55,9 +55,9 @@ fn nonempty() { match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - match_guarded_arm!(0u8); //~ ERROR `_` not covered - match_guarded_arm!(0i8); //~ ERROR `_` not covered - match_guarded_arm!(0usize); //~ ERROR `_` not covered + match_guarded_arm!(0u8); //~ ERROR `0_u8..=u8::MAX` not covered + match_guarded_arm!(0i8); //~ ERROR `i8::MIN..=i8::MAX` not covered + match_guarded_arm!(0usize); //~ ERROR `0_usize..` not covered match_guarded_arm!(0isize); //~ ERROR `_` not covered match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered From 6b175a848d72f0ea60d80de3bd74d0806a64c40f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 6 Feb 2024 16:35:19 +1100 Subject: [PATCH 643/676] Add `SubdiagnosticMessageOp` as a trait alias. It avoids a lot of repetition. --- compiler/rustc_ast_lowering/src/errors.rs | 14 ++---- compiler/rustc_ast_passes/src/errors.rs | 18 ++----- compiler/rustc_builtin_macros/src/errors.rs | 12 ++--- compiler/rustc_errors/src/diagnostic.rs | 7 +-- compiler/rustc_errors/src/diagnostic_impls.rs | 4 +- compiler/rustc_errors/src/lib.rs | 2 + compiler/rustc_hir_typeck/src/errors.rs | 22 ++------- compiler/rustc_infer/src/errors/mod.rs | 47 ++++--------------- .../src/errors/note_and_explain.rs | 7 +-- compiler/rustc_lint/src/errors.rs | 7 +-- compiler/rustc_lint/src/lints.rs | 47 ++++--------------- .../src/diagnostics/subdiagnostic.rs | 5 +- compiler/rustc_mir_build/src/errors.rs | 12 ++--- compiler/rustc_parse/src/errors.rs | 9 ++-- compiler/rustc_passes/src/errors.rs | 3 +- compiler/rustc_pattern_analysis/src/errors.rs | 7 +-- compiler/rustc_trait_selection/src/errors.rs | 7 +-- .../ui-fulldeps/internal-lints/diagnostics.rs | 11 ++--- .../internal-lints/diagnostics.stderr | 8 ++-- 19 files changed, 68 insertions(+), 181 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index ec92afee47a6b..6225358569573 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -1,4 +1,6 @@ -use rustc_errors::{codes::*, DiagnosticArgFromDisplay}; +use rustc_errors::{ + codes::*, AddToDiagnostic, Diagnostic, DiagnosticArgFromDisplay, SubdiagnosticMessageOp, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -38,14 +40,8 @@ pub struct InvalidAbi { pub struct InvalidAbiReason(pub &'static str); -impl rustc_errors::AddToDiagnostic for InvalidAbiReason { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { +impl AddToDiagnostic for InvalidAbiReason { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { #[allow(rustc::untranslatable_diagnostic)] diag.note(self.0); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 5f54a0ddf8c38..9662c73ca8532 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,7 +1,7 @@ //! Errors emitted by ast_passes. use rustc_ast::ParamKindOrd; -use rustc_errors::{codes::*, AddToDiagnostic, Applicability}; +use rustc_errors::{codes::*, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -372,13 +372,7 @@ pub struct EmptyLabelManySpans(pub Vec); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl AddToDiagnostic for EmptyLabelManySpans { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.span_labels(self.0, ""); } } @@ -735,13 +729,7 @@ pub struct StableFeature { } impl AddToDiagnostic for StableFeature { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.arg("name", self.name); diag.arg("since", self.since); diag.help(fluent::ast_passes_stable_since); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index eadb48ddd36d8..8d2e06bf30dac 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, - Level, MultiSpan, SingleLabelManySpans, + codes::*, AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee, + IntoDiagnostic, Level, MultiSpan, SingleLabelManySpans, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -611,13 +611,7 @@ pub(crate) struct FormatUnusedArg { // Allow the singular form to be a subdiagnostic of the multiple-unused // form of diagnostic. impl AddToDiagnostic for FormatUnusedArg { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { diag.arg("named", self.named); let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); diag.span_label(self.span, msg); diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 1763c355069a9..03717a4d654c7 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -77,11 +77,12 @@ where /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used /// (to optionally perform eager translation). - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F); } +pub trait SubdiagnosticMessageOp = + Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; + /// Trait implemented by lint types. This should not be implemented manually. Instead, use /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. #[rustc_diagnostic_item = "DecorateLint"] diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 15effd3cbec9b..e936ebc7185fa 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -2,7 +2,7 @@ use crate::diagnostic::DiagnosticLocation; use crate::{fluent_generated as fluent, AddToDiagnostic}; use crate::{ DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic, - IntoDiagnosticArg, Level, + IntoDiagnosticArg, Level, SubdiagnosticMessageOp, }; use rustc_ast as ast; use rustc_ast_pretty::pprust; @@ -299,7 +299,7 @@ pub struct SingleLabelManySpans { pub label: &'static str, } impl AddToDiagnostic for SingleLabelManySpans { - fn add_to_diagnostic_with(self, diag: &mut crate::Diagnostic, _: F) { + fn add_to_diagnostic_with(self, diag: &mut crate::Diagnostic, _: F) { diag.span_labels(self.spans, self.label); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a4112d717d029..26cf4e7a44332 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -19,6 +19,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] // tidy-alphabetical-end @@ -35,6 +36,7 @@ pub use codes::*; pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName, DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, StringPart, SubDiagnostic, + SubdiagnosticMessageOp, }; pub use diagnostic_builder::{ BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic, diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 70afb042441f9..10e12d01b1fe6 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, - MultiSpan, SubdiagnosticMessage, + MultiSpan, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -195,10 +195,7 @@ pub struct TypeMismatchFruTypo { } impl AddToDiagnostic for TypeMismatchFruTypo { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up @@ -373,10 +370,7 @@ pub struct RemoveSemiForCoerce { } impl AddToDiagnostic for RemoveSemiForCoerce { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret); @@ -547,14 +541,8 @@ pub enum CastUnknownPointerSub { From(Span), } -impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn( - &mut Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { +impl AddToDiagnostic for CastUnknownPointerSub { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { match self { CastUnknownPointerSub::To(span) => { let msg = f(diag, crate::fluent_generated::hir_typeck_label_to); diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 0a128218c9229..8bfc05d6a96db 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1,7 +1,7 @@ use hir::GenericParamKind; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, - DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage, + DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp, }; use rustc_hir as hir; use rustc_hir::FnRetTy; @@ -225,10 +225,7 @@ pub enum RegionOriginNote<'a> { } impl AddToDiagnostic for RegionOriginNote<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut label_or_note = |span, msg: DiagnosticMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); @@ -289,10 +286,7 @@ pub enum LifetimeMismatchLabels { } impl AddToDiagnostic for LifetimeMismatchLabels { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { diag.span_label(param_span, fluent::infer_declared_different); @@ -336,10 +330,7 @@ pub struct AddLifetimeParamsSuggestion<'a> { } impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut mk_suggestion = || { let ( hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. }, @@ -437,10 +428,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { } impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { - fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, _: F) { self.unmet_requirements .push_span_label(self.binding_span, fluent::infer_msl_introduces_static); diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req); @@ -755,10 +743,7 @@ pub struct ConsiderBorrowingParamHelp { } impl AddToDiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required @@ -799,10 +784,7 @@ pub struct DynTraitConstraintSuggestion { } impl AddToDiagnostic for DynTraitConstraintSuggestion { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label); multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement); @@ -845,10 +827,7 @@ pub struct ReqIntroducedLocations { } impl AddToDiagnostic for ReqIntroducedLocations { - fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, f: F) { for sp in self.spans { self.span.push_span_label(sp, fluent::infer_ril_introduced_here); } @@ -867,10 +846,7 @@ pub struct MoreTargeted { } impl AddToDiagnostic for MoreTargeted { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _f: F) { diag.code(E0772); diag.primary_message(fluent::infer_more_targeted); diag.arg("ident", self.ident); @@ -1289,10 +1265,7 @@ pub struct SuggestTuplePatternMany { } impl AddToDiagnostic for SuggestTuplePatternMany { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { diag.arg("path", self.path); let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into()); diag.multipart_suggestions( diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 331e3633e908d..a59a4df77296d 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -1,6 +1,6 @@ use crate::fluent_generated as fluent; use crate::infer::error_reporting::nice_region_error::find_anon_type; -use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage}; +use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessageOp}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{symbol::kw, Span}; @@ -160,10 +160,7 @@ impl RegionExplanation<'_> { } impl AddToDiagnostic for RegionExplanation<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { diag.arg("pref_kind", self.prefix); diag.arg("suff_kind", self.suffix); diag.arg("desc_kind", self.desc.kind); diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 3bd0c1b803199..21d4b6fa65b5b 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,5 +1,5 @@ use crate::fluent_generated as fluent; -use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessage}; +use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; @@ -24,10 +24,7 @@ pub enum OverruledAttributeSub { } impl AddToDiagnostic for OverruledAttributeSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(fluent::lint_default_source); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index f916deb4a46d1..40b68941b17fe 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,7 +6,7 @@ use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, - DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle, + DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessageOp, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -268,10 +268,7 @@ pub struct SuggestChangingAssocTypes<'a, 'b> { } impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { // Access to associates types should use `::Assoc`, which does not need a // bound. Let's see if this type does that. @@ -323,10 +320,7 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion { } impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.multipart_suggestion( fluent::lint_suggestion, self.suggestions, @@ -443,10 +437,7 @@ pub struct BuiltinUnpermittedTypeInitSub { } impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut err = self.err; loop { if let Some(span) = err.span { @@ -497,10 +488,7 @@ pub struct BuiltinClashingExternSub<'a> { } impl AddToDiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut expected_str = DiagnosticStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); let mut found_str = DiagnosticStyledString::new(); @@ -766,10 +754,7 @@ pub struct HiddenUnicodeCodepointsDiagLabels { } impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); } @@ -783,10 +768,7 @@ pub enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( @@ -934,10 +916,7 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; if can_suggest_binding { @@ -1217,10 +1196,7 @@ pub enum NonSnakeCaseDiagSub { } impl AddToDiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, fluent::lint_label); @@ -1413,10 +1389,7 @@ pub enum OverflowingBinHexSign { } impl AddToDiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { OverflowingBinHexSign::Positive => { diag.note(fluent::lint_positive_note); diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index c029b931e7dde..3a5f289559e6a 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -89,10 +89,7 @@ impl SubdiagnosticDeriveBuilder { gen impl rustc_errors::AddToDiagnostic for @Self { fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F) where - __F: core::ops::Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage - ) -> rustc_errors::SubdiagnosticMessage, + __F: rustc_errors::SubdiagnosticMessageOp, { #implementation } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 232b6033946a0..0bc5fe6ef89ac 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,7 +2,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagnosticArgValue; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage, + IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -420,10 +420,7 @@ pub struct UnsafeNotInheritedLintNote { } impl AddToDiagnostic for UnsafeNotInheritedLintNote { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); let body_start = self.body_span.shrink_to_lo(); let body_end = self.body_span.shrink_to_hi(); @@ -866,10 +863,7 @@ pub struct Variant { } impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 86a64d90deb20..3c3a8d6fbb9c7 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,8 +3,8 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level, - SubdiagnosticMessage, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -1475,10 +1475,7 @@ pub(crate) struct FnTraitMissingParen { } impl AddToDiagnostic for FnTraitMissingParen { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn(&mut rustc_errors::Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); let applicability = if self.machine_applicable { Applicability::MachineApplicable diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 77bfe57e3706f..bd827c1bb78df 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -8,6 +8,7 @@ use rustc_ast::Label; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, + SubdiagnosticMessageOp, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -1760,7 +1761,7 @@ pub struct UnusedVariableStringInterp { } impl AddToDiagnostic for UnusedVariableStringInterp { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); diag.multipart_suggestion( crate::fluent_generated::passes_string_interpolation_only_works, diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 88770b0c43b37..d29013be2ad60 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage}; +use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::thir::Pat; use rustc_middle::ty::Ty; @@ -59,10 +59,7 @@ pub struct Overlap<'tcx> { } impl<'tcx> AddToDiagnostic for Overlap<'tcx> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let Overlap { span, range } = self; // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 7894f8dd98fff..20cd573f46e9b 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessage, + EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::Diagnostic; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; @@ -102,10 +102,7 @@ pub enum AdjustSignatureBorrow { } impl AddToDiagnostic for AdjustSignatureBorrow { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("len", to_borrow.len()); diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index ab42d3b8c1e4e..5a2099865d6a7 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -14,7 +14,7 @@ extern crate rustc_span; use rustc_errors::{ AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, DiagCtxt, - IntoDiagnostic, Level, SubdiagnosticMessage, + IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -55,9 +55,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagn pub struct UntranslatableInAddToDiagnostic; impl AddToDiagnostic for UntranslatableInAddToDiagnostic { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.note("untranslatable diagnostic"); //~^ ERROR diagnostics should be created using translatable messages @@ -67,10 +65,7 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic { pub struct TranslatableInAddToDiagnostic; impl AddToDiagnostic for TranslatableInAddToDiagnostic { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.note(crate::fluent_generated::no_crate_note); } } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index f70240ecf172a..108b7c8ea9cbb 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -11,13 +11,13 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:62:14 + --> $DIR/diagnostics.rs:60:14 | LL | diag.note("untranslatable diagnostic"); | ^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:79:21 + --> $DIR/diagnostics.rs:74:21 | LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example); | ^^^^^^^^^^ @@ -29,13 +29,13 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:82:21 + --> $DIR/diagnostics.rs:77:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:82:21 + --> $DIR/diagnostics.rs:77:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ From 8a5847f5c40be178d3dd6fa7ce6fecfb837cabbb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Feb 2024 08:18:55 +0000 Subject: [PATCH 644/676] Already poison the `type_of` result of the anon const used in the `typeof` expression --- .../rustc_hir_analysis/src/astconv/mod.rs | 22 ++++--------------- .../rustc_hir_analysis/src/collect/type_of.rs | 16 ++++++++++++-- tests/rustdoc-ui/issues/issue-102986.stderr | 4 ++-- tests/ui/typeof/issue-100183.stderr | 4 ++-- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index cfd38fb48f472..32722066109f8 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -12,7 +12,7 @@ use crate::astconv::errors::prohibit_assoc_ty_binding; use crate::astconv::generics::{check_generic_arg_count, create_args_for_parent_generic_args}; use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; -use crate::errors::{AmbiguousLifetimeBound, TypeofReservedKeywordUsed}; +use crate::errors::AmbiguousLifetimeBound; use crate::middle::resolve_bound_vars as rbv; use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; @@ -30,8 +30,8 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::{ - self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty, - TyCtxt, TypeVisitableExt, + self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; @@ -2539,21 +2539,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ty::new_array_with_const_len(tcx, self.ast_ty_to_ty(ty), length) } - hir::TyKind::Typeof(e) => { - let ty_erased = tcx.type_of(e.def_id).instantiate_identity(); - let ty = tcx.fold_regions(ty_erased, |r, _| { - if r.is_erased() { tcx.lifetimes.re_static } else { r } - }); - let span = ast_ty.span; - let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) { - (ty, Some((span, Applicability::MachineApplicable))) - } else { - (ty, None) - }; - tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); - - ty - } + hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(), hir::TyKind::Infer => { // Infer also appears as the type of arguments or return // values in an ExprKind::Closure, or as diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 5cdcc1bb860b2..f4e6adb6b8395 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -9,6 +9,8 @@ use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, Ty use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; +use crate::errors::TypeofReservedKeywordUsed; + use super::bad_placeholder; use super::ItemCtxt; pub use opaque::test_opaque_hidden_types; @@ -39,8 +41,18 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { { return tcx.types.usize; } - Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => { - return tcx.typeck(def_id).node_type(e.hir_id); + Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => { + let ty = tcx.typeck(def_id).node_type(e.hir_id); + let ty = tcx.fold_regions(ty, |r, _| { + if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r } + }); + let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) { + (ty, Some((span, Applicability::MachineApplicable))) + } else { + (ty, None) + }; + tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); + return ty; } Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) diff --git a/tests/rustdoc-ui/issues/issue-102986.stderr b/tests/rustdoc-ui/issues/issue-102986.stderr index 996eb41c492b0..d91f93f394a5b 100644 --- a/tests/rustdoc-ui/issues/issue-102986.stderr +++ b/tests/rustdoc-ui/issues/issue-102986.stderr @@ -6,8 +6,8 @@ LL | y: (typeof("hey"),), | help: consider replacing `typeof(...)` with an actual type | -LL | y: (&'static str,), - | ~~~~~~~~~~~~ +LL | y: (&str,), + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/typeof/issue-100183.stderr b/tests/ui/typeof/issue-100183.stderr index 7be923d938357..57317d449cf3a 100644 --- a/tests/ui/typeof/issue-100183.stderr +++ b/tests/ui/typeof/issue-100183.stderr @@ -6,8 +6,8 @@ LL | y: (typeof("hey"),), | help: consider replacing `typeof(...)` with an actual type | -LL | y: (&'static str,), - | ~~~~~~~~~~~~ +LL | y: (&str,), + | ~~~~ error: aborting due to 1 previous error From 1fcd04ed49f2591e8667694bc623fde0ff6e42bc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Feb 2024 08:35:37 +0000 Subject: [PATCH 645/676] inline a function that is only used in clippy --- compiler/rustc_hir/src/hir.rs | 4 ---- src/tools/clippy/clippy_lints/src/lifetimes.rs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ff50086ff8f98..c89ad0794481f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -163,10 +163,6 @@ impl Lifetime { (LifetimeSuggestionPosition::Normal, self.ident.span) } } - - pub fn is_static(&self) -> bool { - self.res == LifetimeName::Static - } } /// A `Path` is essentially Rust's notion of a name; for instance, diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index ffef84d1fadec..f5636945f2037 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -176,7 +176,7 @@ fn check_fn_inner<'tcx>( _ => None, }); for bound in lifetimes { - if !bound.is_static() && !bound.is_elided() { + if bound.res != LifetimeName::Static && !bound.is_elided() { return; } } From e5461de39287fcec2179bb7051f65d987cdff270 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Feb 2024 22:42:36 +0000 Subject: [PATCH 646/676] Taint borrowck results without running any borrowck if the MIR body was already tainted --- compiler/rustc_borrowck/src/lib.rs | 9 +-- tests/ui/consts/promoted_const_call.stderr | 22 +------- tests/ui/consts/promoted_const_call3.rs | 7 ++- tests/ui/consts/promoted_const_call3.stderr | 55 ++++--------------- tests/ui/consts/promoted_const_call5.rs | 4 +- tests/ui/consts/promoted_const_call5.stderr | 22 +------- .../drop-elaboration-after-borrowck-error.rs | 2 - ...op-elaboration-after-borrowck-error.stderr | 34 ++---------- tests/ui/static/static-drop-scope.rs | 2 - tests/ui/static/static-drop-scope.stderr | 39 +++---------- 10 files changed, 38 insertions(+), 158 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index bb64571889bae..4dba34c11f945 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -111,14 +111,16 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { let (input_body, promoted) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); - if input_body.borrow().should_skip() { - debug!("Skipping borrowck because of injected body"); + let input_body: &Body<'_> = &input_body.borrow(); + + if input_body.should_skip() || input_body.tainted_by_errors.is_some() { + debug!("Skipping borrowck because of injected body or tainted body"); // Let's make up a borrowck result! Fun times! let result = BorrowCheckResult { concrete_opaque_types: FxIndexMap::default(), closure_requirements: None, used_mut_upvars: SmallVec::new(), - tainted_by_errors: None, + tainted_by_errors: input_body.tainted_by_errors, }; return tcx.arena.alloc(result); } @@ -127,7 +129,6 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); - let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0; debug!("mir_borrowck done"); diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr index 1f6abc0ce7c82..ace449fae9ce6 100644 --- a/tests/ui/consts/promoted_const_call.stderr +++ b/tests/ui/consts/promoted_const_call.stderr @@ -6,26 +6,6 @@ LL | let _: &'static _ = &id(&Panic); | | | the destructor for this type cannot be evaluated in constants -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:11:26 - | -LL | let _: &'static _ = &id(&Panic); - | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use - | | - | type annotation requires that borrow lasts for `'static` -... -LL | }; - | - temporary value is freed at the end of this statement - -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:11:30 - | -LL | let _: &'static _ = &id(&Panic); - | ---------- ^^^^^ - temporary value is freed at the end of this statement - | | | - | | creates a temporary value which is freed while still in use - | type annotation requires that borrow lasts for `'static` - error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call.rs:17:26 | @@ -68,7 +48,7 @@ LL | let _: &'static _ = &&(Panic, 0).1; LL | } | - temporary value is freed at the end of this statement -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0493, E0716. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/promoted_const_call3.rs b/tests/ui/consts/promoted_const_call3.rs index 6d68a2de70e47..dc05a3b584424 100644 --- a/tests/ui/consts/promoted_const_call3.rs +++ b/tests/ui/consts/promoted_const_call3.rs @@ -2,13 +2,14 @@ pub const fn id(x: T) -> T { x } pub const C: () = { let _: &'static _ = &String::new(); //~^ ERROR: destructor of `String` cannot be evaluated at compile-time - //~| ERROR: temporary value dropped while borrowed +}; +pub const _: () = { let _: &'static _ = &id(&String::new()); //~^ ERROR: destructor of `String` cannot be evaluated at compile-time - //~| ERROR: temporary value dropped while borrowed - //~| ERROR: temporary value dropped while borrowed +}; +pub const _: () = { let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); //~^ ERROR: temporary value dropped while borrowed }; diff --git a/tests/ui/consts/promoted_const_call3.stderr b/tests/ui/consts/promoted_const_call3.stderr index af17457a10a1b..34c833d5bb77c 100644 --- a/tests/ui/consts/promoted_const_call3.stderr +++ b/tests/ui/consts/promoted_const_call3.stderr @@ -1,53 +1,22 @@ -error[E0493]: destructor of `String` cannot be evaluated at compile-time - --> $DIR/promoted_const_call3.rs:7:30 - | -LL | let _: &'static _ = &id(&String::new()); - | ^^^^^^^^^^^^^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constants - error[E0493]: destructor of `String` cannot be evaluated at compile-time --> $DIR/promoted_const_call3.rs:3:26 | LL | let _: &'static _ = &String::new(); | ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants -... +LL | LL | }; | - value is dropped here -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:3:26 - | -LL | let _: &'static _ = &String::new(); - | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use - | | - | type annotation requires that borrow lasts for `'static` -... -LL | }; - | - temporary value is freed at the end of this statement - -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:7:26 - | -LL | let _: &'static _ = &id(&String::new()); - | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use - | | - | type annotation requires that borrow lasts for `'static` -... -LL | }; - | - temporary value is freed at the end of this statement - -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:7:30 +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call3.rs:8:30 | LL | let _: &'static _ = &id(&String::new()); - | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement - | | | - | | creates a temporary value which is freed while still in use - | type annotation requires that borrow lasts for `'static` + | ^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:12:26 + --> $DIR/promoted_const_call3.rs:13:26 | LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -58,7 +27,7 @@ LL | }; | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:17:26 + --> $DIR/promoted_const_call3.rs:18:26 | LL | let _: &'static _ = &String::new(); | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -69,7 +38,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:20:26 + --> $DIR/promoted_const_call3.rs:21:26 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -80,7 +49,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:20:30 + --> $DIR/promoted_const_call3.rs:21:30 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement @@ -89,7 +58,7 @@ LL | let _: &'static _ = &id(&String::new()); | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:24:26 + --> $DIR/promoted_const_call3.rs:25:26 | LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -99,7 +68,7 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to 10 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0493, E0716. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/promoted_const_call5.rs b/tests/ui/consts/promoted_const_call5.rs index 3ac8d358ce485..41b3988949e65 100644 --- a/tests/ui/consts/promoted_const_call5.rs +++ b/tests/ui/consts/promoted_const_call5.rs @@ -25,9 +25,9 @@ pub const fn new_manually_drop(t: T) -> std::mem::ManuallyDrop { const C: () = { let _: &'static _ = &id(&new_string()); //~^ ERROR destructor of `String` cannot be evaluated at compile-time - //~| ERROR: temporary value dropped while borrowed - //~| ERROR: temporary value dropped while borrowed +}; +const _: () = { let _: &'static _ = &new_manually_drop(new_string()); //~^ ERROR: temporary value dropped while borrowed }; diff --git a/tests/ui/consts/promoted_const_call5.stderr b/tests/ui/consts/promoted_const_call5.stderr index f736220b18333..1b5fa4352837e 100644 --- a/tests/ui/consts/promoted_const_call5.stderr +++ b/tests/ui/consts/promoted_const_call5.stderr @@ -6,26 +6,6 @@ LL | let _: &'static _ = &id(&new_string()); | | | the destructor for this type cannot be evaluated in constants -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call5.rs:26:26 - | -LL | let _: &'static _ = &id(&new_string()); - | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use - | | - | type annotation requires that borrow lasts for `'static` -... -LL | }; - | - temporary value is freed at the end of this statement - -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call5.rs:26:30 - | -LL | let _: &'static _ = &id(&new_string()); - | ----^^^^^^^^^^^^-- temporary value is freed at the end of this statement - | | | - | | creates a temporary value which is freed while still in use - | argument requires that borrow lasts for `'static` - error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call5.rs:31:26 | @@ -68,7 +48,7 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0493, E0716. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.rs b/tests/ui/mir/drop-elaboration-after-borrowck-error.rs index 624b464ecef25..cbca3eebf19d1 100644 --- a/tests/ui/mir/drop-elaboration-after-borrowck-error.rs +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.rs @@ -6,7 +6,6 @@ static A: () = { //~^ ERROR destructor of a[0] = String::new(); //~^ ERROR destructor of - //~| ERROR binding `a` isn't initialized }; struct B([T; 1]); @@ -17,7 +16,6 @@ impl B { //~^ ERROR destructor of self.0[0] = other; //~^ ERROR destructor of - //~| ERROR use of moved value self } } diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr index d961061729d4c..22d05fa4ddab0 100644 --- a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -16,22 +16,8 @@ LL | let a: [String; 1]; LL | }; | - value is dropped here -error[E0381]: used binding `a` isn't initialized - --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 - | -LL | let a: [String; 1]; - | - binding declared here but left uninitialized -LL | -LL | a[0] = String::new(); - | ^^^^ `a` used here but it isn't initialized - | -help: consider assigning a value - | -LL | let a: [String; 1] = todo!(); - | +++++++++ - error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 + --> $DIR/drop-elaboration-after-borrowck-error.rs:17:9 | LL | self.0[0] = other; | ^^^^^^^^^ @@ -40,7 +26,7 @@ LL | self.0[0] = other; | value is dropped here error[E0493]: destructor of `B` cannot be evaluated at compile-time - --> $DIR/drop-elaboration-after-borrowck-error.rs:16:13 + --> $DIR/drop-elaboration-after-borrowck-error.rs:15:13 | LL | let _this = self; | ^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -48,18 +34,6 @@ LL | let _this = self; LL | } | - value is dropped here -error[E0382]: use of moved value: `self.0` - --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 - | -LL | pub const fn f(mut self, other: T) -> Self { - | -------- move occurs because `self` has type `B`, which does not implement the `Copy` trait -LL | let _this = self; - | ---- value moved here -LL | -LL | self.0[0] = other; - | ^^^^^^^^^ value used here after move - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0381, E0382, E0493. -For more information about an error, try `rustc --explain E0381`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/static/static-drop-scope.rs b/tests/ui/static/static-drop-scope.rs index 34afa9873a388..74b224c9be085 100644 --- a/tests/ui/static/static-drop-scope.rs +++ b/tests/ui/static/static-drop-scope.rs @@ -6,11 +6,9 @@ impl Drop for WithDtor { static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); //~^ ERROR destructor of -//~| ERROR temporary value dropped while borrowed const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); //~^ ERROR destructor of -//~| ERROR temporary value dropped while borrowed static EARLY_DROP_S: i32 = (WithDtor, 0).1; //~^ ERROR destructor of diff --git a/tests/ui/static/static-drop-scope.stderr b/tests/ui/static/static-drop-scope.stderr index cedcb7367949f..2c55161628fb8 100644 --- a/tests/ui/static/static-drop-scope.stderr +++ b/tests/ui/static/static-drop-scope.stderr @@ -6,36 +6,16 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | | | the destructor for this type cannot be evaluated in statics -error[E0716]: temporary value dropped while borrowed - --> $DIR/static-drop-scope.rs:7:60 - | -LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); - | ------^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a static requires that borrow lasts for `'static` - error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:11:59 + --> $DIR/static-drop-scope.rs:10:59 | LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | ^^^^^^^^- value is dropped here | | | the destructor for this type cannot be evaluated in constants -error[E0716]: temporary value dropped while borrowed - --> $DIR/static-drop-scope.rs:11:59 - | -LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); - | ------^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a constant requires that borrow lasts for `'static` - error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:15:28 + --> $DIR/static-drop-scope.rs:13:28 | LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here @@ -43,7 +23,7 @@ LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | the destructor for this type cannot be evaluated in statics error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:18:27 + --> $DIR/static-drop-scope.rs:16:27 | LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here @@ -51,7 +31,7 @@ LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:21:24 + --> $DIR/static-drop-scope.rs:19:24 | LL | const fn const_drop(_: T) {} | ^ - value is dropped here @@ -59,7 +39,7 @@ LL | const fn const_drop(_: T) {} | the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:25:5 + --> $DIR/static-drop-scope.rs:23:5 | LL | (x, ()).1 | ^^^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -68,7 +48,7 @@ LL | } | - value is dropped here error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:29:34 + --> $DIR/static-drop-scope.rs:27:34 | LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | ^^^^^^^^^^^^^^^^^^^ - value is dropped here @@ -76,14 +56,13 @@ LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:34:43 + --> $DIR/static-drop-scope.rs:32:43 | LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; | ^^^^^^^^^^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constants -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0493, E0716. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0493`. From eab2adb6607d94fd0c70de93abf546ae9282afaa Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Feb 2024 22:45:00 +0000 Subject: [PATCH 647/676] Continue to borrowck even if there were previous errors --- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 21 +- compiler/rustc_mir_build/src/build/scope.rs | 12 +- .../src/ffi_unwind_calls.rs | 1 + compiler/rustc_parse/src/parser/expr.rs | 12 +- compiler/rustc_passes/src/liveness.rs | 10 +- .../incremental/const-generics/issue-62536.rs | 3 + .../issue-77708-1.rs | 2 +- tests/incremental/struct_change_field_name.rs | 1 + tests/ui/asm/bad-template.aarch64.stderr | 52 +-- tests/ui/asm/bad-template.rs | 3 + tests/ui/asm/bad-template.x86_64.stderr | 52 +-- tests/ui/asm/naked-functions.rs | 16 +- tests/ui/asm/naked-functions.stderr | 78 ++--- .../associated-types-eq-hr.rs | 10 + .../associated-types-eq-hr.stderr | 111 ++++++- .../async-await/issue-70935-complex-spans.rs | 1 + .../issue-70935-complex-spans.stderr | 47 ++- .../typeck-auto-trait-no-supertraits-2.rs | 1 + .../typeck-auto-trait-no-supertraits-2.stderr | 19 +- tests/ui/binop/issue-77910-1.rs | 2 +- tests/ui/binop/issue-77910-1.stderr | 17 +- tests/ui/binop/issue-77910-2.rs | 2 +- tests/ui/binop/issue-77910-2.stderr | 18 +- tests/ui/class-cast-to-trait.rs | 8 +- .../diagnostics/borrowck/borrowck-4.rs | 2 +- tests/ui/closures/binder/implicit-stuff.rs | 1 + .../ui/closures/binder/implicit-stuff.stderr | 11 +- tests/ui/closures/issue-109188.rs | 4 +- .../cmse-nonsecure-entry/wrong-abi.rs | 7 +- .../cmse-nonsecure-entry/wrong-abi.stderr | 2 +- tests/ui/const-generics/issues/issue-90318.rs | 2 + .../const-generics/issues/issue-90318.stderr | 27 +- .../late-bound-in-return-issue-77357.stderr | 34 +- tests/ui/consts/const-for-feature-gate.rs | 3 + tests/ui/consts/const-for-feature-gate.stderr | 35 +- tests/ui/consts/const-try-feature-gate.rs | 2 + tests/ui/consts/const-try-feature-gate.stderr | 27 +- tests/ui/consts/control-flow/loop.rs | 6 + tests/ui/consts/control-flow/loop.stderr | 73 ++++- tests/ui/consts/control-flow/try.rs | 2 + tests/ui/consts/control-flow/try.stderr | 27 +- tests/ui/consts/fn_trait_refs.stderr | 98 +++++- .../transmute-size-mismatch-before-typeck.rs | 2 +- ...ansmute-size-mismatch-before-typeck.stderr | 8 +- tests/ui/consts/try-operator.stderr | 49 ++- .../unstable-const-fn-in-libcore.stderr | 35 +- tests/ui/diagnostic-width/tabs-trimming.rs | 1 + .../ui/diagnostic-width/tabs-trimming.stderr | 16 +- .../ui/enum/enum-and-module-in-same-scope.rs | 1 + .../enum/enum-and-module-in-same-scope.stderr | 13 +- tests/ui/error-codes/E0582.rs | 2 +- tests/ui/error-codes/E0582.stderr | 19 +- tests/ui/error-codes/E0637.rs | 4 +- tests/ui/error-codes/E0637.stderr | 20 +- .../explicit-tail-calls/return-mismatches.rs | 2 +- .../return-mismatches.stderr | 13 +- tests/ui/expr/if/if-no-match-bindings.rs | 1 + tests/ui/expr/if/if-no-match-bindings.stderr | 30 +- .../feature-gate-cfg-target-thread-local.rs | 1 + ...eature-gate-cfg-target-thread-local.stderr | 13 +- .../feature-gates/feature-gate-custom_mir.rs | 7 +- .../feature-gate-custom_mir.stderr | 22 +- .../feature-gate-naked_functions.rs | 2 + .../feature-gate-naked_functions.stderr | 23 +- .../feature-gated-feature-in-macro-arg.rs | 2 +- .../feature-gated-feature-in-macro-arg.stderr | 13 +- tests/ui/fn/suggest-return-closure.rs | 10 +- tests/ui/fn/suggest-return-closure.stderr | 29 +- .../extended/lending_iterator.base.stderr | 8 +- .../extended/lending_iterator.rs | 1 + .../generic-associated-types/issue-70304.rs | 1 + .../issue-70304.stderr | 18 +- .../generic-associated-types/issue-74684-2.rs | 2 +- .../issue-74684-2.stderr | 21 +- .../generic-associated-types/issue-80433.rs | 5 +- .../issue-80433.stderr | 41 ++- tests/ui/generics/generic-extern.rs | 2 +- tests/ui/generics/generic-extern.stderr | 13 +- ...gate-half-open-range-patterns-in-slices.rs | 1 + ...-half-open-range-patterns-in-slices.stderr | 19 +- ...nge-pats-inclusive-dotdotdot-bad-syntax.rs | 1 + ...pats-inclusive-dotdotdot-bad-syntax.stderr | 21 +- ...f-open-range-pats-inclusive-match-arrow.rs | 3 + ...en-range-pats-inclusive-match-arrow.stderr | 18 +- .../half-open-range-pats-inclusive-no-end.rs | 2 + ...lf-open-range-pats-inclusive-no-end.stderr | 43 ++- .../slice_pattern_syntax_problem1.rs | 1 + .../slice_pattern_syntax_problem1.stderr | 19 +- .../subtype/placeholder-pattern-fail.rs | 2 + .../subtype/placeholder-pattern-fail.stderr | 18 +- .../hrtb-higher-ranker-supertraits.rs | 4 +- .../hrtb-higher-ranker-supertraits.stderr | 27 +- .../must_outlive_least_region_or_bound.rs | 4 + .../must_outlive_least_region_or_bound.stderr | 68 +++- .../impl-trait/normalize-tait-in-const.stderr | 26 +- .../infinite/infinite-tag-type-recursion.rs | 1 + .../infinite-tag-type-recursion.stderr | 15 +- ...invalid_rustc_layout_scalar_valid_range.rs | 4 +- tests/ui/issues/issue-11374.rs | 1 + tests/ui/issues/issue-11374.stderr | 16 +- tests/ui/issues/issue-13497.rs | 1 + tests/ui/issues/issue-13497.stderr | 14 +- tests/ui/issues/issue-2848.rs | 1 + tests/ui/issues/issue-2848.stderr | 13 +- tests/ui/issues/issue-28971.rs | 1 + tests/ui/issues/issue-28971.stderr | 16 +- tests/ui/kindck/kindck-impl-type-params.rs | 1 + .../ui/kindck/kindck-impl-type-params.stderr | 15 +- tests/ui/kindck/kindck-send-object1.rs | 1 + tests/ui/kindck/kindck-send-object1.stderr | 12 +- tests/ui/lifetimes/issue-17728.rs | 2 +- tests/ui/lifetimes/issue-17728.stderr | 18 +- .../ex1b-return-no-names-if-else.rs | 2 + .../ex1b-return-no-names-if-else.stderr | 18 +- tests/ui/liveness/liveness-forgot-ret.rs | 1 + tests/ui/liveness/liveness-forgot-ret.stderr | 15 +- tests/ui/loops/loop-else-break-with-value.rs | 5 + .../loops/loop-else-break-with-value.stderr | 23 +- tests/ui/methods/assign-to-method.rs | 2 +- .../closure-arg-type-mismatch.rs | 3 + .../closure-arg-type-mismatch.stderr | 50 ++- tests/ui/nll/continue-after-missing-main.rs | 2 + .../ui/nll/continue-after-missing-main.stderr | 36 ++- tests/ui/or-patterns/missing-bindings.rs | 4 +- tests/ui/or-patterns/missing-bindings.stderr | 86 +++-- tests/ui/parser/bad-let-else-statement.rs | 20 +- tests/ui/parser/bad-let-else-statement.stderr | 303 ++++++++++++++++-- .../issues/issue-35813-postfix-after-cast.rs | 1 + .../issue-35813-postfix-after-cast.stderr | 39 ++- .../issues/issue-87086-colon-path-sep.rs | 3 +- .../issues/issue-87086-colon-path-sep.stderr | 20 +- tests/ui/parser/recover/recover-range-pats.rs | 9 + .../parser/recover/recover-range-pats.stderr | 176 +++++++++- .../variadic-ffi-semantic-restrictions.rs | 5 +- .../variadic-ffi-semantic-restrictions.stderr | 79 +++-- .../pat-at-same-name-both.rs | 4 +- .../pat-at-same-name-both.stderr | 26 +- .../pattern/pattern-binding-disambiguation.rs | 4 +- .../pattern-binding-disambiguation.stderr | 51 ++- ...ion-lifetime-bounds-on-fns-where-clause.rs | 4 +- ...lifetime-bounds-on-fns-where-clause.stderr | 31 +- ...ple-lifetime-bounds-on-fns-where-clause.rs | 4 +- ...lifetime-bounds-on-fns-where-clause.stderr | 31 +- .../regions/regions-lifetime-bounds-on-fns.rs | 4 +- .../regions-lifetime-bounds-on-fns.stderr | 31 +- .../ICE-119271-never-arm-attr-in-guard.rs | 3 +- .../ICE-119271-never-arm-attr-in-guard.stderr | 31 +- .../rfcs/rfc-0000-never_patterns/bindings.rs | 1 + .../rfc-0000-never_patterns/bindings.stderr | 16 +- .../ui/rfcs/rfc-0000-never_patterns/check.rs | 6 +- .../rfcs/rfc-0000-never_patterns/check.stderr | 41 ++- .../rfc-2091-track-caller/error-with-naked.rs | 8 +- .../error-with-naked.stderr | 4 +- .../rfc-2396-target_feature-11/fn-traits.rs | 2 +- .../fn-traits.stderr | 12 +- .../const-closure-trait-method-fail.stderr | 16 +- .../const-closure-trait-method.stderr | 16 +- .../const-closures.stderr | 42 ++- .../rfc-2632-const-trait-impl/staged-api.rs | 8 +- .../staged-api.stable.stderr | 30 +- .../staged-api.unstable.stderr | 10 +- .../std-impl-gate.gated.stderr | 14 +- tests/ui/span/issue-23827.rs | 1 + tests/ui/span/issue-23827.stderr | 2 +- tests/ui/span/issue-39698.rs | 1 + tests/ui/span/issue-39698.stderr | 17 +- .../ui/specialization/const_trait_impl.stderr | 30 +- ...nst-stability-attribute-implies-missing.rs | 1 + ...stability-attribute-implies-missing.stderr | 10 +- .../structs-enums/enum-rec/issue-17431-6.rs | 3 + .../enum-rec/issue-17431-6.stderr | 17 +- .../derive-trait-for-method-call.rs | 2 +- ...t-static-bound-needing-more-suggestions.rs | 3 + ...atic-bound-needing-more-suggestions.stderr | 50 ++- ...on-dyn-trait-with-implicit-static-bound.rs | 2 + ...yn-trait-with-implicit-static-bound.stderr | 64 +++- .../impl-trait-missing-lifetime.rs | 1 + .../impl-trait-missing-lifetime.stderr | 12 +- tests/ui/suggestions/issue-102892.rs | 1 + tests/ui/suggestions/issue-102892.stderr | 27 +- tests/ui/suggestions/issue-86667.rs | 7 +- tests/ui/suggestions/issue-86667.stderr | 11 +- .../suggestions/missing-lifetime-specifier.rs | 12 + .../missing-lifetime-specifier.stderr | 232 +++++++++++++- tests/ui/suggestions/missing-lt-for-hrtb.rs | 2 + .../ui/suggestions/missing-lt-for-hrtb.stderr | 24 +- .../self-without-lifetime-constraint.rs | 1 + .../self-without-lifetime-constraint.stderr | 16 +- .../implied_lifetime_wf_check4_static.rs | 1 + .../implied_lifetime_wf_check4_static.stderr | 16 +- tests/ui/type-alias-impl-trait/issue-77179.rs | 1 + .../type-alias-impl-trait/issue-77179.stderr | 16 +- .../no_inferrable_concrete_type.rs | 4 +- .../unboxed-closure-sugar-region.rs | 1 + .../unboxed-closure-sugar-region.stderr | 20 +- .../underscore-lifetime-binders.rs | 1 + .../underscore-lifetime-binders.stderr | 10 +- 198 files changed, 3211 insertions(+), 483 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 2e85da98269cf..b12e134471d07 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -209,7 +209,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.ensure().check_unused_traits(()); - if let Some(reported) = tcx.dcx().has_errors() { Err(reported) } else { Ok(()) } + Ok(()) } /// A quasi-deprecated helper used in rustdoc and clippy to get diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 9a2f2ceced1ed..c24f2e9f53a84 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -666,7 +666,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - let yield_ty = args.yield_ty(); let return_ty = args.return_ty(); ( - vec![closure_ty, args.resume_ty()], + vec![closure_ty, resume_ty], return_ty, Some(Box::new(CoroutineInfo::initial( tcx.coroutine_kind(def_id).unwrap(), @@ -675,8 +675,23 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - ))), ) } - _ => { - span_bug!(span, "expected type of closure body to be a closure or coroutine"); + ty::CoroutineClosure(did, _args) => { + // FIXME(async_closures): Recover the proper error signature + let inputs = tcx + .closure_user_provided_sig(did.expect_local()) + .value + .skip_binder() + .inputs(); + + let err = Ty::new_error(tcx, guar); + (inputs.iter().map(|_| err).collect(), err, None) + } + ty::Error(_) => (vec![closure_ty, closure_ty], closure_ty, None), + kind => { + span_bug!( + span, + "expected type of closure body to be a closure or coroutine, got {kind:?}" + ); } } } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 6827797df372c..2d3669487718b 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -655,7 +655,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let drops = if destination.is_some() { &mut self.scopes.breakable_scopes[break_index].break_drops } else { - self.scopes.breakable_scopes[break_index].continue_drops.as_mut().unwrap() + let Some(drops) = self.scopes.breakable_scopes[break_index].continue_drops.as_mut() + else { + self.tcx.dcx().span_delayed_bug( + source_info.span, + "unlabelled `continue` within labelled block", + ); + self.cfg.terminate(block, source_info, TerminatorKind::Unreachable); + + return self.cfg.start_new_block().unit(); + }; + drops }; let drop_idx = self.scopes.scopes[scope_index + 1..] diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index b0d758bcbfe3b..663abbece851d 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -59,6 +59,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { ty::Closure(..) => Abi::RustCall, ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + ty::Error(_) => return false, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e36a648e2032e..1a57474bac289 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2911,12 +2911,22 @@ impl<'a> Parser<'a> { Ok(arm) => arms.push(arm), Err(e) => { // Recover by skipping to the end of the block. - e.emit(); + let guar = e.emit(); self.recover_stmt(); let span = lo.to(self.token.span); if self.token == token::CloseDelim(Delimiter::Brace) { self.bump(); } + // Always push at least one arm to make the match non-empty + arms.push(Arm { + attrs: Default::default(), + pat: self.mk_pat(span, ast::PatKind::Err(guar)), + guard: None, + body: Some(self.mk_expr_err(span)), + span, + id: DUMMY_NODE_ID, + is_placeholder: false, + }); return Ok(self.mk_expr_with_attrs( span, ExprKind::Match(scrutinee, arms), diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index f7c382bcd7a40..3a8dc3775206c 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -123,6 +123,7 @@ enum LiveNodeKind { VarDefNode(Span, HirId), ClosureNode, ExitNode, + ErrNode, } fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { @@ -133,6 +134,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { VarDefNode(s, _) => format!("Var def node [{}]", sm.span_to_diagnostic_string(s)), ClosureNode => "Closure node".to_owned(), ExitNode => "Exit node".to_owned(), + ErrNode => "Error node".to_owned(), } } @@ -967,10 +969,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Now that we know the label we're going to, // look it up in the continue loop nodes table - self.cont_ln - .get(&sc) - .cloned() - .unwrap_or_else(|| span_bug!(expr.span, "continue to unknown label")) + self.cont_ln.get(&sc).cloned().unwrap_or_else(|| { + self.ir.tcx.dcx().span_delayed_bug(expr.span, "continue to unknown label"); + self.ir.add_live_node(ErrNode) + }) } hir::ExprKind::Assign(ref l, ref r, _) => { diff --git a/tests/incremental/const-generics/issue-62536.rs b/tests/incremental/const-generics/issue-62536.rs index 93c1dbf44e938..022376768f2a5 100644 --- a/tests/incremental/const-generics/issue-62536.rs +++ b/tests/incremental/const-generics/issue-62536.rs @@ -1,4 +1,7 @@ // revisions:cfail1 + +#![allow(unused_variables)] + struct S([T; N]); fn f(x: T) -> S { panic!() } diff --git a/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs index 8262a2a211b7e..5c8af47ccbe8f 100644 --- a/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs +++ b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs @@ -1,6 +1,6 @@ // revisions: cfail #![feature(generic_const_exprs)] -#![allow(incomplete_features, unused_braces)] +#![allow(incomplete_features, unused_braces, unused_variables)] trait Delegates {} diff --git a/tests/incremental/struct_change_field_name.rs b/tests/incremental/struct_change_field_name.rs index a7c79e9d751e0..bd952bcc1c89a 100644 --- a/tests/incremental/struct_change_field_name.rs +++ b/tests/incremental/struct_change_field_name.rs @@ -6,6 +6,7 @@ // [cfail2] compile-flags: -Z query-dep-graph -Z assert-incr-state=loaded #![feature(rustc_attrs)] +#![allow(unused_variables)] #[cfg(rpass1)] pub struct X { diff --git a/tests/ui/asm/bad-template.aarch64.stderr b/tests/ui/asm/bad-template.aarch64.stderr index 4ffcd2303b74f..b18946d7c6d85 100644 --- a/tests/ui/asm/bad-template.aarch64.stderr +++ b/tests/ui/asm/bad-template.aarch64.stderr @@ -1,5 +1,5 @@ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:27:15 + --> $DIR/bad-template.rs:30:15 | LL | asm!("{}"); | ^^ from here @@ -7,7 +7,7 @@ LL | asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:29:15 + --> $DIR/bad-template.rs:32:15 | LL | asm!("{1}", in(reg) foo); | ^^^ from here @@ -15,7 +15,7 @@ LL | asm!("{1}", in(reg) foo); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:29:21 + --> $DIR/bad-template.rs:32:21 | LL | asm!("{1}", in(reg) foo); | ^^^^^^^^^^^ argument never used @@ -23,13 +23,13 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:32:16 + --> $DIR/bad-template.rs:35:16 | LL | asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:34:15 + --> $DIR/bad-template.rs:37:15 | LL | asm!("{}", a = in(reg) foo); | ^^ --------------- named argument @@ -38,13 +38,13 @@ LL | asm!("{}", a = in(reg) foo); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -52,7 +52,7 @@ LL | asm!("{}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:37:15 + --> $DIR/bad-template.rs:40:15 | LL | asm!("{1}", a = in(reg) foo); | ^^^ from here @@ -60,7 +60,7 @@ LL | asm!("{1}", a = in(reg) foo); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:37:21 + --> $DIR/bad-template.rs:40:21 | LL | asm!("{1}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -68,7 +68,7 @@ LL | asm!("{1}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:44:15 + --> $DIR/bad-template.rs:47:15 | LL | asm!("{}", in("x0") foo); | ^^ ------------ explicit register argument @@ -77,24 +77,24 @@ LL | asm!("{}", in("x0") foo); | = note: no positional arguments were given note: explicit register arguments cannot be used in the asm template - --> $DIR/bad-template.rs:44:20 + --> $DIR/bad-template.rs:47:20 | LL | asm!("{}", in("x0") foo); | ^^^^^^^^^^^^ help: use the register name directly in the assembly code - --> $DIR/bad-template.rs:44:20 + --> $DIR/bad-template.rs:47:20 | LL | asm!("{}", in("x0") foo); | ^^^^^^^^^^^^ error: asm template modifier must be a single character - --> $DIR/bad-template.rs:46:17 + --> $DIR/bad-template.rs:49:17 | LL | asm!("{:foo}", in(reg) foo); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:49:18 + --> $DIR/bad-template.rs:52:18 | LL | asm!("", in(reg) 0, in(reg) 1); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -104,7 +104,7 @@ LL | asm!("", in(reg) 0, in(reg) 1); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:55:14 + --> $DIR/bad-template.rs:58:14 | LL | global_asm!("{}"); | ^^ from here @@ -112,7 +112,7 @@ LL | global_asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:57:14 + --> $DIR/bad-template.rs:60:14 | LL | global_asm!("{1}", const FOO); | ^^^ from here @@ -120,7 +120,7 @@ LL | global_asm!("{1}", const FOO); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:57:20 + --> $DIR/bad-template.rs:60:20 | LL | global_asm!("{1}", const FOO); | ^^^^^^^^^ argument never used @@ -128,13 +128,13 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:60:15 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:62:14 + --> $DIR/bad-template.rs:65:14 | LL | global_asm!("{}", a = const FOO); | ^^ ------------- named argument @@ -143,13 +143,13 @@ LL | global_asm!("{}", a = const FOO); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -157,7 +157,7 @@ LL | global_asm!("{}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:65:14 + --> $DIR/bad-template.rs:68:14 | LL | global_asm!("{1}", a = const FOO); | ^^^ from here @@ -165,7 +165,7 @@ LL | global_asm!("{1}", a = const FOO); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:65:20 + --> $DIR/bad-template.rs:68:20 | LL | global_asm!("{1}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -173,13 +173,13 @@ LL | global_asm!("{1}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: asm template modifier must be a single character - --> $DIR/bad-template.rs:68:16 + --> $DIR/bad-template.rs:71:16 | LL | global_asm!("{:foo}", const FOO); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:70:17 + --> $DIR/bad-template.rs:73:17 | LL | global_asm!("", const FOO, const FOO); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -189,7 +189,7 @@ LL | global_asm!("", const FOO, const FOO); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` warning: formatting may not be suitable for sub-register argument - --> $DIR/bad-template.rs:46:15 + --> $DIR/bad-template.rs:49:15 | LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument diff --git a/tests/ui/asm/bad-template.rs b/tests/ui/asm/bad-template.rs index a6a233a36ec38..b70da4921c20f 100644 --- a/tests/ui/asm/bad-template.rs +++ b/tests/ui/asm/bad-template.rs @@ -21,6 +21,9 @@ macro_rules! global_asm { #[lang = "sized"] trait Sized {} +#[lang = "copy"] +trait Copy {} + fn main() { let mut foo = 0; unsafe { diff --git a/tests/ui/asm/bad-template.x86_64.stderr b/tests/ui/asm/bad-template.x86_64.stderr index 52a7789b98cc1..2f584c30a3282 100644 --- a/tests/ui/asm/bad-template.x86_64.stderr +++ b/tests/ui/asm/bad-template.x86_64.stderr @@ -1,5 +1,5 @@ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:27:15 + --> $DIR/bad-template.rs:30:15 | LL | asm!("{}"); | ^^ from here @@ -7,7 +7,7 @@ LL | asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:29:15 + --> $DIR/bad-template.rs:32:15 | LL | asm!("{1}", in(reg) foo); | ^^^ from here @@ -15,7 +15,7 @@ LL | asm!("{1}", in(reg) foo); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:29:21 + --> $DIR/bad-template.rs:32:21 | LL | asm!("{1}", in(reg) foo); | ^^^^^^^^^^^ argument never used @@ -23,13 +23,13 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:32:16 + --> $DIR/bad-template.rs:35:16 | LL | asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:34:15 + --> $DIR/bad-template.rs:37:15 | LL | asm!("{}", a = in(reg) foo); | ^^ --------------- named argument @@ -38,13 +38,13 @@ LL | asm!("{}", a = in(reg) foo); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -52,7 +52,7 @@ LL | asm!("{}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:37:15 + --> $DIR/bad-template.rs:40:15 | LL | asm!("{1}", a = in(reg) foo); | ^^^ from here @@ -60,7 +60,7 @@ LL | asm!("{1}", a = in(reg) foo); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:37:21 + --> $DIR/bad-template.rs:40:21 | LL | asm!("{1}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -68,7 +68,7 @@ LL | asm!("{1}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:41:15 + --> $DIR/bad-template.rs:44:15 | LL | asm!("{}", in("eax") foo); | ^^ ------------- explicit register argument @@ -77,24 +77,24 @@ LL | asm!("{}", in("eax") foo); | = note: no positional arguments were given note: explicit register arguments cannot be used in the asm template - --> $DIR/bad-template.rs:41:20 + --> $DIR/bad-template.rs:44:20 | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ help: use the register name directly in the assembly code - --> $DIR/bad-template.rs:41:20 + --> $DIR/bad-template.rs:44:20 | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ error: asm template modifier must be a single character - --> $DIR/bad-template.rs:46:17 + --> $DIR/bad-template.rs:49:17 | LL | asm!("{:foo}", in(reg) foo); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:49:18 + --> $DIR/bad-template.rs:52:18 | LL | asm!("", in(reg) 0, in(reg) 1); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -104,7 +104,7 @@ LL | asm!("", in(reg) 0, in(reg) 1); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:55:14 + --> $DIR/bad-template.rs:58:14 | LL | global_asm!("{}"); | ^^ from here @@ -112,7 +112,7 @@ LL | global_asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:57:14 + --> $DIR/bad-template.rs:60:14 | LL | global_asm!("{1}", const FOO); | ^^^ from here @@ -120,7 +120,7 @@ LL | global_asm!("{1}", const FOO); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:57:20 + --> $DIR/bad-template.rs:60:20 | LL | global_asm!("{1}", const FOO); | ^^^^^^^^^ argument never used @@ -128,13 +128,13 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:60:15 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:62:14 + --> $DIR/bad-template.rs:65:14 | LL | global_asm!("{}", a = const FOO); | ^^ ------------- named argument @@ -143,13 +143,13 @@ LL | global_asm!("{}", a = const FOO); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -157,7 +157,7 @@ LL | global_asm!("{}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:65:14 + --> $DIR/bad-template.rs:68:14 | LL | global_asm!("{1}", a = const FOO); | ^^^ from here @@ -165,7 +165,7 @@ LL | global_asm!("{1}", a = const FOO); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:65:20 + --> $DIR/bad-template.rs:68:20 | LL | global_asm!("{1}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -173,13 +173,13 @@ LL | global_asm!("{1}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: asm template modifier must be a single character - --> $DIR/bad-template.rs:68:16 + --> $DIR/bad-template.rs:71:16 | LL | global_asm!("{:foo}", const FOO); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:70:17 + --> $DIR/bad-template.rs:73:17 | LL | global_asm!("", const FOO, const FOO); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -189,7 +189,7 @@ LL | global_asm!("", const FOO, const FOO); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` warning: formatting may not be suitable for sub-register argument - --> $DIR/bad-template.rs:46:15 + --> $DIR/bad-template.rs:49:15 | LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 2f3716ca77f65..b18d01730f299 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -81,13 +81,15 @@ pub extern "C" fn missing_assembly() { #[naked] pub extern "C" fn too_many_asm_blocks() { //~^ ERROR naked functions must contain a single asm block - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!("", options(noreturn)); + unsafe { + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!("", options(noreturn)); + } } pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index f90967fbe6e43..6613c3dfdbafb 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -1,23 +1,23 @@ error: asm with the `pure` option must have at least one output - --> $DIR/naked-functions.rs:111:14 + --> $DIR/naked-functions.rs:113:14 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:203:5 + --> $DIR/naked-functions.rs:205:5 | LL | compile_error!("this is a user specified error") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:209:5 + --> $DIR/naked-functions.rs:211:5 | LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:216:10 + --> $DIR/naked-functions.rs:218:10 | LL | asm!(invalid_syntax) | ^^^^^^^^^^^^^^ @@ -142,37 +142,37 @@ LL | pub extern "C" fn missing_assembly() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:84:5 + --> $DIR/naked-functions.rs:85:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:86:5 + --> $DIR/naked-functions.rs:87:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:88:5 + --> $DIR/naked-functions.rs:89:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: naked functions must contain a single asm block --> $DIR/naked-functions.rs:82:1 @@ -180,17 +180,17 @@ error[E0787]: naked functions must contain a single asm block LL | pub extern "C" fn too_many_asm_blocks() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | asm!(""); - | -------- multiple asm blocks are unsupported in naked functions +LL | asm!(""); + | -------- multiple asm blocks are unsupported in naked functions LL | -LL | asm!(""); - | -------- multiple asm blocks are unsupported in naked functions +LL | asm!(""); + | -------- multiple asm blocks are unsupported in naked functions LL | -LL | asm!("", options(noreturn)); - | --------------------------- multiple asm blocks are unsupported in naked functions +LL | asm!("", options(noreturn)); + | --------------------------- multiple asm blocks are unsupported in naked functions error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:97:11 + --> $DIR/naked-functions.rs:99:11 | LL | *&y | ^ @@ -198,7 +198,7 @@ LL | *&y = help: follow the calling convention in asm block to use parameters error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:95:5 + --> $DIR/naked-functions.rs:97:5 | LL | pub extern "C" fn inner(y: usize) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,19 +207,19 @@ LL | *&y | --- non-asm is unsupported in naked functions error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags` - --> $DIR/naked-functions.rs:105:5 + --> $DIR/naked-functions.rs:107:5 | LL | asm!("", options(nomem, preserves_flags, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly` - --> $DIR/naked-functions.rs:111:5 + --> $DIR/naked-functions.rs:113:5 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:111:5 + --> $DIR/naked-functions.rs:113:5 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -230,13 +230,13 @@ LL | asm!("", options(noreturn), options(readonly, nostack), options(pure)); | +++++++++++++++++++ error[E0787]: asm options unsupported in naked functions: `may_unwind` - --> $DIR/naked-functions.rs:119:5 + --> $DIR/naked-functions.rs:121:5 | LL | asm!("", options(noreturn, may_unwind)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:124:1 + --> $DIR/naked-functions.rs:126:1 | LL | pub unsafe fn default_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -244,43 +244,43 @@ LL | pub unsafe fn default_abi() { = note: `#[warn(undefined_naked_function_abi)]` on by default warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:130:1 + --> $DIR/naked-functions.rs:132:1 | LL | pub unsafe fn rust_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:170:1 + --> $DIR/naked-functions.rs:172:1 | LL | #[inline] | ^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:177:1 + --> $DIR/naked-functions.rs:179:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:184:1 + --> $DIR/naked-functions.rs:186:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:191:1 + --> $DIR/naked-functions.rs:193:1 | LL | #[inline] | ^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:193:1 + --> $DIR/naked-functions.rs:195:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:195:1 + --> $DIR/naked-functions.rs:197:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/associated-types/associated-types-eq-hr.rs b/tests/ui/associated-types/associated-types-eq-hr.rs index dc653f7f2e9dc..b8a97b5c7dd2c 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.rs +++ b/tests/ui/associated-types/associated-types-eq-hr.rs @@ -94,10 +94,18 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::(); + //~^ ERROR not general enough + //~| ERROR not general enough + //~| ERROR not general enough + //~| ERROR not general enough } pub fn call_tuple_two() { tuple_two::(); + //~^ ERROR not general enough + //~| ERROR not general enough + //~| ERROR mismatched types + //~| ERROR mismatched types } pub fn call_tuple_three() { @@ -106,6 +114,8 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::(); + //~^ ERROR not general enough + //~| ERROR not general enough } fn main() {} diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 3e1142d5d9560..3a70189dd9f94 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -42,6 +42,113 @@ LL | where LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, | ^^^^^^^^^^^^^ required by this bound in `bar` -error: aborting due to 2 previous errors +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&'x _` + found reference `&'y _` +note: the lifetime requirement is introduced here + --> $DIR/associated-types-eq-hr.rs:66:53 + | +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&'x _` + found reference `&'y _` +note: the lifetime requirement is introduced here + --> $DIR/associated-types-eq-hr.rs:66:53 + | +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:116:5 + | +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:116:5 + | +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index 4af73739584cb..81f6961840c14 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -14,6 +14,7 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { fn foo(x: NotSync) -> impl Future + Send { //~^ ERROR `*mut ()` cannot be shared between threads safely + //~| ERROR `*mut ()` cannot be shared between threads safely async move { baz(|| async { foo(x.clone()); diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 36e297ed88422..8dc3f476ec8dd 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 ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:17:5: 21:6}: Send` + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22: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` @@ -14,7 +14,7 @@ LL | struct NotSync(PhantomData<*mut ()>); | ^^^^^^^ = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:18:13 + --> $DIR/issue-70935-complex-spans.rs:19:13 | LL | baz(|| async { | ^^ @@ -27,7 +27,7 @@ LL | | } | |_^ = note: required because it captures the following types: `impl Future` note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:17:5 + --> $DIR/issue-70935-complex-spans.rs:18:5 | LL | / async move { LL | | baz(|| async { @@ -36,6 +36,45 @@ LL | | }).await; LL | | } | |_____^ -error: aborting due to 1 previous error +error[E0277]: `*mut ()` cannot be shared between threads safely + --> $DIR/issue-70935-complex-spans.rs:15:23 + | +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 ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22: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` + --> $DIR/issue-70935-complex-spans.rs:9:8 + | +LL | struct NotSync(PhantomData<*mut ()>); + | ^^^^^^^ + = note: required for `&NotSync` to implement `Send` +note: required because it's used within this closure + --> $DIR/issue-70935-complex-spans.rs:19:13 + | +LL | baz(|| async { + | ^^ +note: required because it's used within this `async` fn body + --> $DIR/issue-70935-complex-spans.rs:12:67 + | +LL | async fn baz(_c: impl FnMut() -> T) where T: Future { + | ___________________________________________________________________^ +LL | | } + | |_^ + = note: required because it captures the following types: `impl Future` +note: required because it's used within this `async` block + --> $DIR/issue-70935-complex-spans.rs:18:5 + | +LL | / async move { +LL | | baz(|| async { +LL | | foo(x.clone()); +LL | | }).await; +LL | | } + | |_____^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs index 98359ef51b764..c0ed1e00f3b48 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs @@ -6,6 +6,7 @@ auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 impl Magic for T {} fn copy(x: T) -> (T, T) { (x, x) } +//~^ ERROR: use of moved value #[derive(Debug)] struct NoClone; diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index 547b4bb54489d..dcf1c02bceefa 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -14,6 +14,21 @@ LL | auto trait Magic : Sized where Option : Magic {} | | | auto traits cannot have super traits or lifetime bounds -error: aborting due to 2 previous errors +error[E0382]: use of moved value: `x` + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:8:41 + | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | - - ^ value used here after move + | | | + | | value moved here + | move occurs because `x` has type `T`, which does not implement the `Copy` trait + | +help: consider further restricting this bound + | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | ++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0568`. +Some errors have detailed explanations: E0382, E0568. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/binop/issue-77910-1.rs b/tests/ui/binop/issue-77910-1.rs index 95bbd6a60ec86..4b7ee77b46dc8 100644 --- a/tests/ui/binop/issue-77910-1.rs +++ b/tests/ui/binop/issue-77910-1.rs @@ -1,6 +1,6 @@ fn foo(s: &i32) -> &i32 { let xs; - xs + xs //~ ERROR: isn't initialized } fn main() { let y; diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr index 263a35d982911..6402e5681884c 100644 --- a/tests/ui/binop/issue-77910-1.stderr +++ b/tests/ui/binop/issue-77910-1.stderr @@ -22,7 +22,20 @@ LL | assert_eq!(foo, y); = help: use parentheses to call this function: `foo(/* &i32 */)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-1.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0369. +Some errors have detailed explanations: E0277, E0369, E0381. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/binop/issue-77910-2.rs b/tests/ui/binop/issue-77910-2.rs index 2bb48d3657617..5ea03e82b2fe9 100644 --- a/tests/ui/binop/issue-77910-2.rs +++ b/tests/ui/binop/issue-77910-2.rs @@ -1,6 +1,6 @@ fn foo(s: &i32) -> &i32 { let xs; - xs + xs //~ ERROR: isn't initialized } fn main() { let y; diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr index e58ae0fad9b4d..a14560ff188ee 100644 --- a/tests/ui/binop/issue-77910-2.stderr +++ b/tests/ui/binop/issue-77910-2.stderr @@ -11,6 +11,20 @@ help: use parentheses to call this function LL | if foo(/* &i32 */) == y {} | ++++++++++++ -error: aborting due to 1 previous error +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-2.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0369`. +Some errors have detailed explanations: E0369, E0381. +For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/class-cast-to-trait.rs b/tests/ui/class-cast-to-trait.rs index 345d6efd2d90a..ca98e4c90031f 100644 --- a/tests/ui/class-cast-to-trait.rs +++ b/tests/ui/class-cast-to-trait.rs @@ -1,5 +1,5 @@ trait Noisy { - fn speak(&self); + fn speak(&mut self); } struct Cat { @@ -10,7 +10,7 @@ struct Cat { } impl Cat { - pub fn eat(&self) -> bool { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { println!("OM NOM NOM"); self.how_hungry -= 2; @@ -24,12 +24,12 @@ impl Cat { } impl Noisy for Cat { - fn speak(&self) { self.meow(); } + fn speak(&mut self) { self.meow(); } } impl Cat { - fn meow(&self) { + fn meow(&mut self) { println!("Meow"); self.meows += 1; if self.meows % 5 == 0 { diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs index a2290d850207d..16f7df1b36347 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs @@ -15,6 +15,6 @@ fn foo () -> impl FnMut()->() { c } fn main() { - let c = foo(); + let mut c = foo(); c(); } diff --git a/tests/ui/closures/binder/implicit-stuff.rs b/tests/ui/closures/binder/implicit-stuff.rs index 09e4c747afee8..c976c200b0c8e 100644 --- a/tests/ui/closures/binder/implicit-stuff.rs +++ b/tests/ui/closures/binder/implicit-stuff.rs @@ -24,4 +24,5 @@ fn main() { //~| ERROR `'_` cannot be used here let _ = for<'a> |x: &()| -> &'a () { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here let _ = for<'a> |x: &'a ()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here + //~^ ERROR: lifetime may not live long enough } diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr index cec2a60ba28c8..330a05a79bae3 100644 --- a/tests/ui/closures/binder/implicit-stuff.stderr +++ b/tests/ui/closures/binder/implicit-stuff.stderr @@ -102,6 +102,15 @@ LL | let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ { | | | `for<...>` is here -error: aborting due to 15 previous errors +error: lifetime may not live long enough + --> $DIR/implicit-stuff.rs:26:42 + | +LL | let _ = for<'a> |x: &'a ()| -> &() { x }; + | -- - ^ returning this value requires that `'a` must outlive `'1` + | | | + | | let's call the lifetime of this reference `'1` + | lifetime `'a` defined here + +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/closures/issue-109188.rs b/tests/ui/closures/issue-109188.rs index cae1ced9958a7..03c8b415774cf 100644 --- a/tests/ui/closures/issue-109188.rs +++ b/tests/ui/closures/issue-109188.rs @@ -7,13 +7,13 @@ struct X(Y); struct Y; -fn consume_fnmut(f: &dyn FnMut()) { +fn consume_fnmut(f: &mut dyn FnMut()) { f(); } fn move_into_fnmut() { let x = move_into_fnmut(); - consume_fnmut(&|| { + consume_fnmut(&mut || { let Either::One(_t) = x; //~ ERROR mismatched types let Either::Two(_t) = x; //~ ERROR mismatched types }); diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs index 6320d296373c0..72c14cd7a6919 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs @@ -2,8 +2,11 @@ // needs-llvm-components: arm #![feature(cmse_nonsecure_entry, no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} #[no_mangle] #[cmse_nonsecure_entry] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr index 4d34f0d75099d..c3fae3d8bbb67 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr @@ -1,5 +1,5 @@ error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI - --> $DIR/wrong-abi.rs:9:1 + --> $DIR/wrong-abi.rs:12:1 | LL | #[cmse_nonsecure_entry] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/issues/issue-90318.rs b/tests/ui/const-generics/issues/issue-90318.rs index 909997340f36e..cebc1ce214208 100644 --- a/tests/ui/const-generics/issues/issue-90318.rs +++ b/tests/ui/const-generics/issues/issue-90318.rs @@ -13,6 +13,7 @@ fn consume(_val: T) where If<{ TypeId::of::() != TypeId::of::<()>() }>: True, //~^ overly complex generic constant + //~| ERROR: cannot call { } @@ -20,6 +21,7 @@ fn test() where If<{ TypeId::of::() != TypeId::of::<()>() }>: True, //~^ overly complex generic constant + //~| ERROR: cannot call { } diff --git a/tests/ui/const-generics/issues/issue-90318.stderr b/tests/ui/const-generics/issues/issue-90318.stderr index f13fd795d7a10..471a6660ce0f3 100644 --- a/tests/ui/const-generics/issues/issue-90318.stderr +++ b/tests/ui/const-generics/issues/issue-90318.stderr @@ -10,7 +10,7 @@ LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, = note: this operation may be supported in the future error: overly complex generic constant - --> $DIR/issue-90318.rs:21:8 + --> $DIR/issue-90318.rs:22:8 | LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, | ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,5 +20,28 @@ LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to 2 previous errors +error[E0015]: cannot call non-const operator in constants + --> $DIR/issue-90318.rs:14:10 + | +LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: cannot call non-const operator in constants + --> $DIR/issue-90318.rs:22:10 + | +LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr b/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr index 1fe0109771c5c..e42bb6e8cc561 100644 --- a/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr +++ b/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr @@ -13,5 +13,37 @@ LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to 2 previous errors +error[E0391]: cycle detected when evaluating type-level constant + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires caching mir of `bug::{constant#0}` for CTFE... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires elaborating drops for `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires borrow-checking `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { def: DefId(0:8 ~ late_bound_in_return_issue_77357[9394]::bug::{constant#0}), args: [T/#0] }: usize), bound_vars: [] }`... + = note: ...which again requires evaluating type-level constant, completing the cycle + = note: cycle used when normalizing `&dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]>` + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs index bec7b80890536..c834046c5b07f 100644 --- a/tests/ui/consts/const-for-feature-gate.rs +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -3,6 +3,9 @@ const _: () = { for _ in 0..5 {} //~^ error: `for` is not allowed in a `const` + //~| ERROR: cannot convert + //~| ERROR: cannot call + //~| ERROR: mutable references }; fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index df79c00f024fd..413d144ca0ac3 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -8,6 +8,37 @@ LL | for _ in 0..5 {} = help: add `#![feature(const_for)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: cannot convert `std::ops::Range` into an iterator in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` 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[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-try-feature-gate.rs b/tests/ui/consts/const-try-feature-gate.rs index 0839c23a0b99b..1cc045bf61249 100644 --- a/tests/ui/consts/const-try-feature-gate.rs +++ b/tests/ui/consts/const-try-feature-gate.rs @@ -3,6 +3,8 @@ const fn t() -> Option<()> { Some(())?; //~^ error: `?` is not allowed in a `const fn` + //~| ERROR: cannot convert + //~| ERROR: cannot determine None } diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr index c5aeed3317cca..efa1fb107f624 100644 --- a/tests/ui/consts/const-try-feature-gate.stderr +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -8,6 +8,29 @@ LL | Some(())?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions + --> $DIR/const-try-feature-gate.rs:4:5 + | +LL | Some(())?; + | ^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions + --> $DIR/const-try-feature-gate.rs:4:5 + | +LL | Some(())?; + | ^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs index 2b8561a264488..5b7f8d29df7c6 100644 --- a/tests/ui/consts/control-flow/loop.rs +++ b/tests/ui/consts/control-flow/loop.rs @@ -51,10 +51,16 @@ const _: i32 = { let mut x = 0; for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + //~^ ERROR: cannot call + //~| ERROR: mutable references + //~| ERROR: cannot convert x += i; } for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + //~^ ERROR: cannot call + //~| ERROR: mutable references + //~| ERROR: cannot convert x += i; } diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr index 725adf723392d..e162a404ace8f 100644 --- a/tests/ui/consts/control-flow/loop.stderr +++ b/tests/ui/consts/control-flow/loop.stderr @@ -2,6 +2,9 @@ error[E0658]: `for` is not allowed in a `const` --> $DIR/loop.rs:53:5 | LL | / for i in 0..4 { +LL | | +LL | | +LL | | LL | | x += i; LL | | } | |_____^ @@ -11,9 +14,12 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:57:5 + --> $DIR/loop.rs:60:5 | LL | / for i in 0..4 { +LL | | +LL | | +LL | | LL | | x += i; LL | | } | |_____^ @@ -22,6 +28,67 @@ LL | | } = help: add `#![feature(const_for)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0015]: cannot convert `std::ops::Range` into an iterator in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` 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[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: cannot convert `std::ops::Range` into an iterator in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` 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[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/try.rs b/tests/ui/consts/control-flow/try.rs index 7d85a412b4722..5c6957df40566 100644 --- a/tests/ui/consts/control-flow/try.rs +++ b/tests/ui/consts/control-flow/try.rs @@ -4,6 +4,8 @@ const fn opt() -> Option { let x = Some(2); x?; //~ ERROR `?` is not allowed in a `const fn` + //~^ ERROR: cannot convert + //~| ERROR: cannot determine None } diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr index f4b88de9dfab3..f4c42c4d819b9 100644 --- a/tests/ui/consts/control-flow/try.stderr +++ b/tests/ui/consts/control-flow/try.stderr @@ -8,6 +8,29 @@ LL | x?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Option` in constant functions + --> $DIR/try.rs:6:5 + | +LL | x?; + | ^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option` in constant functions + --> $DIR/try.rs:6:5 + | +LL | x?; + | ^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index e6ea4108f4045..afe89461f031f 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -74,6 +74,100 @@ LL | T: ~const FnMut<()> + ~const Destruct, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 11 previous errors +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:17:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const Fn<()> + ~const Destruct + ~const std::ops::Fn<()>, + | +++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:13:23 + | +LL | const fn tester_fn(f: T) -> T::Output + | ^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:24:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const FnMut<()> + ~const Destruct + ~const std::ops::FnMut<()>, + | ++++++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:20:27 + | +LL | const fn tester_fn_mut(mut f: T) -> T::Output + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:31:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const FnOnce<()> + ~const std::ops::FnOnce<()>, + | +++++++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:34:21 + | +LL | const fn test_fn(mut f: T) -> (T::Output, T::Output, T::Output) + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:48:25 + | +LL | const fn test_fn_mut(mut f: T) -> (T::Output, T::Output) + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const operator in constants + --> $DIR/fn_trait_refs.rs:72:17 + | +LL | assert!(test_one == (1, 1, 1)); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const operator in constants + --> $DIR/fn_trait_refs.rs:75:17 + | +LL | assert!(test_two == (2, 2)); + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 20 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0493, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs index 852a5b3b46a21..936931acbe2c8 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs @@ -5,7 +5,7 @@ fn main() { match &b""[..] { - ZST => {} + ZST => {} //~ ERROR: could not evaluate constant pattern } } diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr index 6bc7e7203aa74..e0d658db99760 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -7,6 +7,12 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; = note: source type: `usize` (word size) = note: target type: `&[u8]` (2 * word size) -error: aborting due to 1 previous error +error: could not evaluate constant pattern + --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9 + | +LL | ZST => {} + | ^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr index bb8f606edf8e8..c19d1a6199d83 100644 --- a/tests/ui/consts/try-operator.stderr +++ b/tests/ui/consts/try-operator.stderr @@ -4,6 +4,51 @@ error[E0635]: unknown feature `const_convert` LL | #![feature(const_convert)] | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Result<(), ()>` in constant functions + --> $DIR/try-operator.rs:10:9 + | +LL | Err(())?; + | ^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/result.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Result` in constant functions + --> $DIR/try-operator.rs:10:9 + | +LL | Err(())?; + | ^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/result.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions + --> $DIR/try-operator.rs:18:9 + | +LL | None?; + | ^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions + --> $DIR/try-operator.rs:18:9 + | +LL | None?; + | ^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 08147a4afaf37..ee4a0f6a8436b 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -4,5 +4,38 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn unwrap_or_else T>(self, f: F) -> T { | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/unstable-const-fn-in-libcore.rs:24:26 + | +LL | Opt::None => f(), + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn unwrap_or_else T + ~const std::ops::FnOnce<()>>(self, f: F) -> T { + | +++++++++++++++++++++++++++++ + +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:19:60 + | +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0493]: destructor of `Opt` cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:19:54 + | +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error: aborting due to 4 previous errors +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/diagnostic-width/tabs-trimming.rs b/tests/ui/diagnostic-width/tabs-trimming.rs index ade21753b457c..96babde33e9a4 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.rs +++ b/tests/ui/diagnostic-width/tabs-trimming.rs @@ -8,6 +8,7 @@ match money { v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT //~^ ERROR variable `v` is not bound in all patterns + //~| ERROR possibly-uninitialized v => println!("Enough money {}", v), } } diff --git a/tests/ui/diagnostic-width/tabs-trimming.stderr b/tests/ui/diagnostic-width/tabs-trimming.stderr index 2aa4fc18c3d65..85103fbf6f591 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.stderr +++ b/tests/ui/diagnostic-width/tabs-trimming.stderr @@ -7,6 +7,18 @@ LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Lon | | pattern doesn't bind `v` | variable not in all patterns -error: aborting due to 1 previous error +error[E0381]: used binding `v` is possibly-uninitialized + --> $DIR/tabs-trimming.rs:9:67 + | +LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT... + | - ^ `v` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions + | binding declared here but left uninitialized + | + = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0381, E0408. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/enum/enum-and-module-in-same-scope.rs b/tests/ui/enum/enum-and-module-in-same-scope.rs index cc6e199bd7ca0..8e69c89d792ff 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.rs +++ b/tests/ui/enum/enum-and-module-in-same-scope.rs @@ -5,6 +5,7 @@ enum Foo { mod Foo { //~ ERROR the name `Foo` is defined multiple times pub static X: isize = 42; fn f() { f() } // Check that this does not result in a resolution error + //~^ WARN cannot return without recursing } fn main() {} diff --git a/tests/ui/enum/enum-and-module-in-same-scope.stderr b/tests/ui/enum/enum-and-module-in-same-scope.stderr index 0293acd6201b2..f1c02af595ffd 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.stderr +++ b/tests/ui/enum/enum-and-module-in-same-scope.stderr @@ -9,6 +9,17 @@ LL | mod Foo { | = note: `Foo` must be defined only once in the type namespace of this module -error: aborting due to 1 previous error +warning: function cannot return without recursing + --> $DIR/enum-and-module-in-same-scope.rs:7:5 + | +LL | fn f() { f() } // Check that this does not result in a resolution error + | ^^^^^^ --- recursive call site + | | + | cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/error-codes/E0582.rs b/tests/ui/error-codes/E0582.rs index ff25012d0f925..b6513170b137e 100644 --- a/tests/ui/error-codes/E0582.rs +++ b/tests/ui/error-codes/E0582.rs @@ -19,7 +19,7 @@ fn mk_unexpected_char_err<'a>() -> Option<&'a i32> { } fn foo<'a>(data: &mut Chars<'a>) { - bar(mk_unexpected_char_err) + bar(mk_unexpected_char_err) //~ ERROR mismatched types } fn bar(t: F) diff --git a/tests/ui/error-codes/E0582.stderr b/tests/ui/error-codes/E0582.stderr index 81a2f004653d2..64b527cdcc2a2 100644 --- a/tests/ui/error-codes/E0582.stderr +++ b/tests/ui/error-codes/E0582.stderr @@ -10,6 +10,21 @@ error[E0582]: binding for associated type `Item` references lifetime `'a`, which LL | where F: for<'a> Iterator | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/E0582.rs:22:5 + | +LL | bar(mk_unexpected_char_err) + | ^^^ one type is more general than the other + | + = note: expected enum `Option<&_>` + found enum `Option<&'a _>` +note: the lifetime requirement is introduced here + --> $DIR/E0582.rs:28:30 + | +LL | where F: for<'a> Fn() -> Option<&'a i32> + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0582`. +Some errors have detailed explanations: E0308, E0582. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0637.rs b/tests/ui/error-codes/E0637.rs index 382ce3ed01f34..e107ea9521b62 100644 --- a/tests/ui/error-codes/E0637.rs +++ b/tests/ui/error-codes/E0637.rs @@ -2,9 +2,9 @@ fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { //~^ ERROR: `'_` cannot be used here [E0637] //~| ERROR: missing lifetime specifier if str1.len() > str2.len() { - str1 + str1 //~ ERROR: lifetime may not live long enough } else { - str2 + str2 //~ ERROR: lifetime may not live long enough } } diff --git a/tests/ui/error-codes/E0637.stderr b/tests/ui/error-codes/E0637.stderr index d9db89ddb0c97..217881b8e7c0e 100644 --- a/tests/ui/error-codes/E0637.stderr +++ b/tests/ui/error-codes/E0637.stderr @@ -27,7 +27,25 @@ help: consider introducing a higher-ranked lifetime here LL | T: for<'a> Into<&'a u32>, | +++++++ ++ -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/E0637.rs:5:9 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | - let's call the lifetime of this reference `'1` +... +LL | str1 + | ^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/E0637.rs:7:9 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | - let's call the lifetime of this reference `'2` +... +LL | str2 + | ^^^^ returning this value requires that `'2` must outlive `'static` + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0106, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/explicit-tail-calls/return-mismatches.rs b/tests/ui/explicit-tail-calls/return-mismatches.rs index 935a1a1d28b02..8094a192913bc 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.rs +++ b/tests/ui/explicit-tail-calls/return-mismatches.rs @@ -13,7 +13,7 @@ fn _f1() { become _g1(); //~ error: mismatched types } -fn _g1() -> ! { +fn _g1() -> ! { //~ WARN: cannot return without recursing become _g1(); } diff --git a/tests/ui/explicit-tail-calls/return-mismatches.stderr b/tests/ui/explicit-tail-calls/return-mismatches.stderr index 1dcc35797c130..31c7a46ded911 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.stderr +++ b/tests/ui/explicit-tail-calls/return-mismatches.stderr @@ -22,6 +22,17 @@ error[E0308]: mismatched types LL | become _g2(); | ^^^^^^^^^^^^ expected `u32`, found `u16` -error: aborting due to 3 previous errors +warning: function cannot return without recursing + --> $DIR/return-mismatches.rs:16:1 + | +LL | fn _g1() -> ! { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | become _g1(); + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-no-match-bindings.rs b/tests/ui/expr/if/if-no-match-bindings.rs index ca3df0fdde45d..d36a436397b46 100644 --- a/tests/ui/expr/if/if-no-match-bindings.rs +++ b/tests/ui/expr/if/if-no-match-bindings.rs @@ -6,6 +6,7 @@ fn b_ref<'a>() -> &'a bool { &true } fn b_mut_ref<'a>() -> &'a mut bool { &mut true } +//~^ ERROR: cannot return reference to temporary fn main() { // This is OK: diff --git a/tests/ui/expr/if/if-no-match-bindings.stderr b/tests/ui/expr/if/if-no-match-bindings.stderr index 737a5d604483f..18f3b6b168ecc 100644 --- a/tests/ui/expr/if/if-no-match-bindings.stderr +++ b/tests/ui/expr/if/if-no-match-bindings.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:18:8 + --> $DIR/if-no-match-bindings.rs:19:8 | LL | if b_ref() {} | ^^^^^^^ expected `bool`, found `&bool` @@ -10,7 +10,7 @@ LL | if *b_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:19:8 + --> $DIR/if-no-match-bindings.rs:20:8 | LL | if b_mut_ref() {} | ^^^^^^^^^^^ expected `bool`, found `&mut bool` @@ -21,7 +21,7 @@ LL | if *b_mut_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:20:8 + --> $DIR/if-no-match-bindings.rs:21:8 | LL | if &true {} | ^^^^^ expected `bool`, found `&bool` @@ -33,7 +33,7 @@ LL + if true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:21:8 + --> $DIR/if-no-match-bindings.rs:22:8 | LL | if &mut true {} | ^^^^^^^^^ expected `bool`, found `&mut bool` @@ -45,7 +45,7 @@ LL + if true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:24:11 + --> $DIR/if-no-match-bindings.rs:25:11 | LL | while b_ref() {} | ^^^^^^^ expected `bool`, found `&bool` @@ -56,7 +56,7 @@ LL | while *b_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:25:11 + --> $DIR/if-no-match-bindings.rs:26:11 | LL | while b_mut_ref() {} | ^^^^^^^^^^^ expected `bool`, found `&mut bool` @@ -67,7 +67,7 @@ LL | while *b_mut_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:26:11 + --> $DIR/if-no-match-bindings.rs:27:11 | LL | while &true {} | ^^^^^ expected `bool`, found `&bool` @@ -79,7 +79,7 @@ LL + while true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:27:11 + --> $DIR/if-no-match-bindings.rs:28:11 | LL | while &mut true {} | ^^^^^^^^^ expected `bool`, found `&mut bool` @@ -90,6 +90,16 @@ LL - while &mut true {} LL + while true {} | -error: aborting due to 8 previous errors +error[E0515]: cannot return reference to temporary value + --> $DIR/if-no-match-bindings.rs:8:38 + | +LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true } + | ^^^^^---- + | | | + | | temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0515. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs index b600ad23eee64..801956c33395d 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs @@ -13,4 +13,5 @@ extern "C" { fn main() { assert_eq!(FOO, 3); + //~^ ERROR extern static is unsafe } diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr index 0e1fe5572a982..62b72e3505994 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr @@ -8,6 +8,15 @@ LL | #[cfg_attr(target_thread_local, thread_local)] = help: add `#![feature(cfg_target_thread_local)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/feature-gate-cfg-target-thread-local.rs:15:16 + | +LL | assert_eq!(FOO, 3); + | ^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.rs b/tests/ui/feature-gates/feature-gate-custom_mir.rs index 0126dde2f7d4b..e100df08ee70d 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.rs +++ b/tests/ui/feature-gates/feature-gate-custom_mir.rs @@ -1,10 +1,15 @@ #![feature(core_intrinsics)] extern crate core; +use core::intrinsics::mir::*; //~ custom_mir #[custom_mir(dialect = "built")] //~ ERROR the `#[custom_mir]` attribute is just used for the Rust test suite pub fn foo(_x: i32) -> i32 { - 0 + mir! { + { + Return() //~ custom_mir + } + } } fn main() { diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.stderr b/tests/ui/feature-gates/feature-gate-custom_mir.stderr index 34899e5e66c08..118eab144bf7f 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.stderr +++ b/tests/ui/feature-gates/feature-gate-custom_mir.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[custom_mir]` attribute is just used for the Rust test suite - --> $DIR/feature-gate-custom_mir.rs:5:1 + --> $DIR/feature-gate-custom_mir.rs:6:1 | LL | #[custom_mir(dialect = "built")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,6 +7,24 @@ LL | #[custom_mir(dialect = "built")] = help: add `#![feature(custom_mir)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable + --> $DIR/feature-gate-custom_mir.rs:4:5 + | +LL | use core::intrinsics::mir::*; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(custom_mir)]` 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]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable + --> $DIR/feature-gate-custom_mir.rs:10:13 + | +LL | Return() + | ^^^^^^ + | + = help: add `#![feature(custom_mir)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs index 8e93b194174ff..dc561234809af 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.rs +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -6,12 +6,14 @@ use std::arch::asm; //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked() { asm!("", options(noreturn)) + //~^ ERROR: requires unsafe } #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked_2() -> isize { asm!("", options(noreturn)) + //~^ ERROR: requires unsafe } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr index e1b826582171f..ffdf31e147aed 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.stderr +++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr @@ -9,7 +9,7 @@ LL | #[naked] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:11:1 + --> $DIR/feature-gate-naked_functions.rs:12:1 | LL | #[naked] | ^^^^^^^^ @@ -18,6 +18,23 @@ LL | #[naked] = help: add `#![feature(naked_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0133]: use of inline assembly is unsafe and requires unsafe function or block + --> $DIR/feature-gate-naked_functions.rs:8:5 + | +LL | asm!("", options(noreturn)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly + | + = note: inline assembly is entirely unchecked and can cause undefined behavior + +error[E0133]: use of inline assembly is unsafe and requires unsafe function or block + --> $DIR/feature-gate-naked_functions.rs:15:5 + | +LL | asm!("", options(noreturn)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly + | + = note: inline assembly is entirely unchecked and can cause undefined behavior + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs index 1285cca6b8b7c..37b7d52fafcae 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs @@ -8,7 +8,7 @@ fn main() { extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change fn atomic_fence(); } - atomic_fence(); + atomic_fence(); //~ ERROR: is unsafe 42 }); } diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr index b0ed6e6076051..3dc11b5612ca9 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr @@ -7,6 +7,15 @@ LL | extern "rust-intrinsic" { = help: add `#![feature(intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0133]: call to unsafe function `main::atomic_fence` is unsafe and requires unsafe function or block + --> $DIR/feature-gated-feature-in-macro-arg.rs:11:9 + | +LL | atomic_fence(); + | ^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs index 33daa1ea0b400..81f2027286791 100644 --- a/tests/ui/fn/suggest-return-closure.rs +++ b/tests/ui/fn/suggest-return-closure.rs @@ -17,10 +17,16 @@ fn fn_mut() -> _ { //~| SUGGESTION impl FnMut(char) //~| NOTE for more information on `Fn` traits and closure types let x = String::new(); - |c| { + //~^ HELP: consider changing this to be mutable + |c| { //~ NOTE: value captured here x.push(c); + //~^ ERROR: does not live long enough + //~| NOTE: does not live long enough + //~| NOTE: cannot borrow as mutable + //~| ERROR: not declared as mutable } -} +} //~ NOTE: borrow later used here +//~^ NOTE: dropped here fn fun() -> _ { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] diff --git a/tests/ui/fn/suggest-return-closure.stderr b/tests/ui/fn/suggest-return-closure.stderr index 341044469ea37..8e80a11fe1b08 100644 --- a/tests/ui/fn/suggest-return-closure.stderr +++ b/tests/ui/fn/suggest-return-closure.stderr @@ -21,7 +21,7 @@ LL | fn fn_mut() -> _ { = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/suggest-return-closure.rs:25:13 + --> $DIR/suggest-return-closure.rs:31:13 | LL | fn fun() -> _ { | ^ @@ -31,6 +31,29 @@ LL | fn fun() -> _ { | = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html -error: aborting due to 3 previous errors +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/suggest-return-closure.rs:22:9 + | +LL | let x = String::new(); + | - help: consider changing this to be mutable: `mut x` +... +LL | x.push(c); + | ^ cannot borrow as mutable + +error[E0597]: `x` does not live long enough + --> $DIR/suggest-return-closure.rs:22:9 + | +LL | |c| { + | --- value captured here +LL | x.push(c); + | ^ borrowed value does not live long enough +... +LL | } + | -- borrow later used here + | | + | `x` dropped here while still borrowed + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0121, E0596, E0597. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr index 84210eeb1a62b..b19280b45c248 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr @@ -7,6 +7,12 @@ LL | fn from_iter LendingIterator = A>>(iter: T) -> Self LL | fn from_iter LendingIterator = A>>(mut iter: I) -> Self { | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` -error: aborting due to 1 previous error +error: `Self` does not live long enough + --> $DIR/lending_iterator.rs:34:9 + | +LL | >::from_iter(self) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.rs b/tests/ui/generic-associated-types/extended/lending_iterator.rs index 247761dd04bf4..8bec78d6ecd7b 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.rs +++ b/tests/ui/generic-associated-types/extended/lending_iterator.rs @@ -32,6 +32,7 @@ pub trait LendingIterator { Self: for<'q> LendingIterator = A>, { >::from_iter(self) + //[base]~^ ERROR: does not live long enough } } diff --git a/tests/ui/generic-associated-types/issue-70304.rs b/tests/ui/generic-associated-types/issue-70304.rs index 8898d4c7d1352..935d3f7a4ba8f 100644 --- a/tests/ui/generic-associated-types/issue-70304.rs +++ b/tests/ui/generic-associated-types/issue-70304.rs @@ -52,4 +52,5 @@ fn create_doc() -> impl Document = DocCursorImpl<'_>> { pub fn main() { let doc = create_doc(); let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); + //~^ ERROR: `doc` does not live long enough } diff --git a/tests/ui/generic-associated-types/issue-70304.stderr b/tests/ui/generic-associated-types/issue-70304.stderr index 9b02c1b076837..8e012cc6d9367 100644 --- a/tests/ui/generic-associated-types/issue-70304.stderr +++ b/tests/ui/generic-associated-types/issue-70304.stderr @@ -27,7 +27,21 @@ LL | type Cursor<'a>: DocCursor<'a>; = note: this bound is currently required to ensure that impls have maximum flexibility = note: we are soliciting feedback, see issue #87479 for more information -error: aborting due to 3 previous errors +error[E0597]: `doc` does not live long enough + --> $DIR/issue-70304.rs:54:59 + | +LL | let doc = create_doc(); + | --- binding `doc` declared here +LL | let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); + | ------------^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `doc` is borrowed for `'static` +LL | +LL | } + | - `doc` dropped here while still borrowed + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0106, E0637. +Some errors have detailed explanations: E0106, E0597, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/generic-associated-types/issue-74684-2.rs b/tests/ui/generic-associated-types/issue-74684-2.rs index ff243af2cb390..96cdb01be3b60 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.rs +++ b/tests/ui/generic-associated-types/issue-74684-2.rs @@ -10,7 +10,7 @@ impl Fun for T { fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { let a = [0; 1]; - let x = T::identity(&a); + let x = T::identity(&a); //~ ERROR: does not live long enough todo!() } diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr index e50e3df85b363..d39513ec523af 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.stderr +++ b/tests/ui/generic-associated-types/issue-74684-2.stderr @@ -17,6 +17,23 @@ note: required by a bound in `bug` LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { | ^^^^^^^^^^^^ required by this bound in `bug` -error: aborting due to 1 previous error +error[E0597]: `a` does not live long enough + --> $DIR/issue-74684-2.rs:13:25 + | +LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { + | -- lifetime `'a` defined here +LL | let a = [0; 1]; + | - binding `a` declared here +LL | let x = T::identity(&a); + | ------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +LL | todo!() +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0597. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-80433.rs b/tests/ui/generic-associated-types/issue-80433.rs index bdba78c2ccd26..6d23427f16f8c 100644 --- a/tests/ui/generic-associated-types/issue-80433.rs +++ b/tests/ui/generic-associated-types/issue-80433.rs @@ -22,11 +22,12 @@ fn test_simpler<'a>(dst: &'a mut impl TestMut) //~^ ERROR missing generics for associated type { for n in 0i16..100 { - *dst.test_mut() = n.into(); + *dst.test_mut() = n.into(); //~ ERROR: cannot borrow + //~^ ERROR: borrowed data escapes outside of function } } fn main() { let mut t1: E = Default::default(); - test_simpler(&mut t1); + test_simpler(&mut t1); //~ ERROR does not live long enough } diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr index ab1fb7944180f..2bbf87ff1ff4f 100644 --- a/tests/ui/generic-associated-types/issue-80433.stderr +++ b/tests/ui/generic-associated-types/issue-80433.stderr @@ -25,6 +25,43 @@ LL | type Output<'a>; = note: this bound is currently required to ensure that impls have maximum flexibility = note: we are soliciting feedback, see issue #87479 for more information -error: aborting due to 2 previous errors +error[E0499]: cannot borrow `*dst` as mutable more than once at a time + --> $DIR/issue-80433.rs:25:10 + | +LL | *dst.test_mut() = n.into(); + | ^^^----------- + | | + | `*dst` was mutably borrowed here in the previous iteration of the loop + | argument requires that `*dst` is borrowed for `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-80433.rs:25:10 + | +LL | fn test_simpler<'a>(dst: &'a mut impl TestMut) + | -- --- `dst` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | *dst.test_mut() = n.into(); + | ^^^^^^^^^^^^^^ + | | + | `dst` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0597]: `t1` does not live long enough + --> $DIR/issue-80433.rs:32:18 + | +LL | let mut t1: E = Default::default(); + | ------ binding `t1` declared here +LL | test_simpler(&mut t1); + | -------------^^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `t1` is borrowed for `'static` +LL | } + | - `t1` dropped here while still borrowed + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0499, E0521, E0597. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-extern.rs b/tests/ui/generics/generic-extern.rs index 3690d6fd07d29..36fa5eaafd672 100644 --- a/tests/ui/generics/generic-extern.rs +++ b/tests/ui/generics/generic-extern.rs @@ -3,5 +3,5 @@ extern "C" { } fn main() { - foo::(); + foo::(); //~ ERROR requires unsafe } diff --git a/tests/ui/generics/generic-extern.stderr b/tests/ui/generics/generic-extern.stderr index 4d9f6fedef14e..a3f2882531638 100644 --- a/tests/ui/generics/generic-extern.stderr +++ b/tests/ui/generics/generic-extern.stderr @@ -6,6 +6,15 @@ LL | fn foo(); | = help: replace the type parameters with concrete types like `u32` -error: aborting due to 1 previous error +error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block + --> $DIR/generic-extern.rs:6:5 + | +LL | foo::(); + | ^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0044`. +Some errors have detailed explanations: E0044, E0133. +For more information about an error, try `rustc --explain E0044`. diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs index dac973473490e..99de7845d7b65 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs @@ -4,4 +4,5 @@ fn main() { let xs = [13, 1, 5, 2, 3, 1, 21, 8]; let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; //~^ `X..` patterns in slices are experimental + //~| ERROR: refutable pattern } diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr index 8ae8f052e5be4..b011044f4ddc4 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr @@ -8,6 +8,21 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0005]: refutable pattern in local binding + --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:5:9 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `[i32; 8]` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0005, E0658. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs index 526a797e9d649..33506a5c444a7 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs @@ -23,6 +23,7 @@ fn syntax2() { macro_rules! mac { ($e:expr) => { let ...$e; //~ ERROR range-to patterns with `...` are not allowed + //~^ ERROR refutable pattern in local binding } } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr index ddffeaf978059..6832f21f25e99 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr @@ -33,5 +33,24 @@ LL | mac!(0); | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 5 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:25:17 + | +LL | let ...$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ...$e; { todo!() } + | ++ +++++++++++ + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs index 30173b1b4be03..cff0c42eb52fc 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs @@ -1,6 +1,9 @@ fn main() { let x = 42; match x { + //~^ ERROR: non-exhaustive patterns + //~| NOTE: not covered + //~| NOTE: matched value is of type 0..=73 => {}, 74..=> {}, //~^ ERROR unexpected `>` after inclusive range diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr index 8dfc46069f13f..ecb43e83c70ee 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr @@ -1,5 +1,5 @@ error: unexpected `>` after inclusive range - --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14 + --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:8:14 | LL | 74..=> {}, | ---^ @@ -11,5 +11,19 @@ help: add a space between the pattern and `=>` LL | 74.. => {}, | + -error: aborting due to 1 previous error +error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` not covered + --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:3:11 + | +LL | match x { + | ^ pattern `i32::MIN..=-1_i32` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 74..=> {}, +LL ~ i32::MIN..=-1_i32 => todo!(), + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs index 6567c8cc67cb0..2f1ec65897211 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs @@ -16,7 +16,9 @@ fn bar() { macro_rules! mac { ($e:expr) => { let $e...; //~ ERROR inclusive range with no end + //~^ ERROR: refutable pattern let $e..=; //~ ERROR inclusive range with no end + //~^ ERROR: refutable pattern } } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr index 3ad84b0ef26f8..cb9e48e70e391 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr @@ -43,7 +43,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/half-open-range-pats-inclusive-no-end.rs:19:19 + --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19 | LL | let $e..=; | ^^^ help: use `..` instead @@ -54,6 +54,43 @@ LL | mac!(0); = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-no-end.rs:18:17 + | +LL | let $e...; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e...; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:17 + | +LL | let $e..=; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..=; { todo!() } + | ++ +++++++++++ + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0586`. +Some errors have detailed explanations: E0005, E0586. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs index c37af75b8fb29..cd38154437266 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs @@ -5,4 +5,5 @@ fn main() { //~^ `X..` patterns in slices are experimental //~| exclusive range pattern syntax is experimental //~| exclusive range pattern syntax is experimental + //~| ERROR: refutable pattern } diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr index be8f3aa5051e3..fc549eb65c0ed 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr @@ -30,6 +30,21 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: use an inclusive range pattern, like N..=M -error: aborting due to 3 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/slice_pattern_syntax_problem1.rs:4:9 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `[i32; 8]` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0005, E0658. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs index bd4533e0433ff..dc865605ed3c0 100644 --- a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs +++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs @@ -12,10 +12,12 @@ fn hr_subtype<'c>(f: for<'a, 'b> fn(Inv<'a>, Inv<'a>)) { fn simple1<'c>(x: (&'c i32,)) { let _x: (&'static i32,) = x; + //~^ ERROR: lifetime may not live long enough } fn simple2<'c>(x: (&'c i32,)) { let _: (&'static i32,) = x; + //~^ ERROR: lifetime may not live long enough } fn main() { diff --git a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr index c6d6f50832829..39d43181ed7d6 100644 --- a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr +++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr @@ -9,6 +9,22 @@ LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub; = note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)` found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/placeholder-pattern-fail.rs:14:13 + | +LL | fn simple1<'c>(x: (&'c i32,)) { + | -- lifetime `'c` defined here +LL | let _x: (&'static i32,) = x; + | ^^^^^^^^^^^^^^^ type annotation requires that `'c` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/placeholder-pattern-fail.rs:19:12 + | +LL | fn simple2<'c>(x: (&'c i32,)) { + | -- lifetime `'c` defined here +LL | let _: (&'static i32,) = x; + | ^^^^^^^^^^^^^^^ type annotation requires that `'c` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs index 48ebe5017aa62..33e0ec4635b66 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs @@ -18,7 +18,7 @@ fn want_foo_for_some_tcx<'x,F>(f: &'x F) want_foo_for_any_tcx(f); //~ ERROR not satisfied } -fn want_foo_for_any_tcx(f: &F) +fn want_foo_for_any_tcx(f: &F) //~ WARN cannot return without recursing where F : for<'tcx> Foo<'tcx> { want_foo_for_some_tcx(f); @@ -35,7 +35,7 @@ fn want_bar_for_some_ccx<'x,B>(b: &B) want_bar_for_any_ccx(b); //~ ERROR not satisfied } -fn want_bar_for_any_ccx(b: &B) +fn want_bar_for_any_ccx(b: &B) //~ WARN cannot return without recursing where B : for<'ccx> Bar<'ccx> { want_foo_for_some_tcx(b); diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr index 7f96909b6e76e..f220ba6f33893 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr @@ -38,6 +38,31 @@ help: consider further restricting this bound LL | where B : Bar<'x> + for<'ccx> Bar<'ccx> | +++++++++++++++++++++ -error: aborting due to 2 previous errors +warning: function cannot return without recursing + --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 + | +LL | / fn want_foo_for_any_tcx(f: &F) +LL | | where F : for<'tcx> Foo<'tcx> + | |_________________________________^ cannot return without recursing +... +LL | want_foo_for_any_tcx(f); + | ----------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: function cannot return without recursing + --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 + | +LL | / fn want_bar_for_any_ccx(b: &B) +LL | | where B : for<'ccx> Bar<'ccx> + | |_________________________________^ cannot return without recursing +... +LL | want_bar_for_any_ccx(b); + | ----------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: aborting due to 2 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs b/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs index 18404f9860317..9762ac982721f 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -16,12 +16,16 @@ fn foo<'a>(x: &i32) -> impl Copy + 'a { x } //~^ ERROR explicit lifetime required in the type of `x` fn elided3(x: &i32) -> Box { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn elided4(x: &i32) -> Box { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } //~^ ERROR lifetime may not live long enough diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr index c60fe08c5d7c5..273f51ddbe35c 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -67,7 +67,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:26:55 + --> $DIR/must_outlive_least_region_or_bound.rs:30:55 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | - ^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` @@ -84,7 +84,7 @@ LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) | ++++ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:32:69 + --> $DIR/must_outlive_least_region_or_bound.rs:36:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -99,12 +99,12 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x | ~~~~~~~~~~~~ error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:38:5 + --> $DIR/must_outlive_least_region_or_bound.rs:42:5 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- ---------------- opaque type defined here | | - | hidden type `{closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13}` captures the lifetime `'b` as defined here + | hidden type `{closure@$DIR/must_outlive_least_region_or_bound.rs:42:5: 42:13}` captures the lifetime `'b` as defined here LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -114,7 +114,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | ++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:43:5 + --> $DIR/must_outlive_least_region_or_bound.rs:47:5 | LL | x | ^ @@ -127,7 +127,63 @@ help: consider adding an explicit lifetime bound LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | +++++++++ -error: aborting due to 9 previous errors +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:18:41 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | - ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ++++ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:21:50 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | -- lifetime `'a` defined here ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ++++ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:24:51 + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | - ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } + | ~~~~~~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | -- lifetime `'a` defined here ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } + | ~~~~~~~~~~~~ + +error: aborting due to 13 previous errors Some errors have detailed explanations: E0310, E0621, E0700. For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 7fd2ec57b1455..f77b4bd517f43 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -4,5 +4,29 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/normalize-tait-in-const.rs:26:5 + | +LL | fun(filter_positive()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) { + | ++++++++++++++++++++++++++++++++++++ + +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/normalize-tait-in-const.rs:25:79 + | +LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^ the destructor for this type cannot be evaluated in constant functions +LL | fun(filter_positive()); +LL | } + | - value is dropped here + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/infinite/infinite-tag-type-recursion.rs b/tests/ui/infinite/infinite-tag-type-recursion.rs index 87a9e08dd381a..1b5cb55b4e4d1 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.rs +++ b/tests/ui/infinite/infinite-tag-type-recursion.rs @@ -1,4 +1,5 @@ enum MList { Cons(isize, MList), Nil } //~^ ERROR recursive type `MList` has infinite size +//~| ERROR cycle fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); } diff --git a/tests/ui/infinite/infinite-tag-type-recursion.stderr b/tests/ui/infinite/infinite-tag-type-recursion.stderr index 4ca408260b84a..8745224a45e13 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.stderr +++ b/tests/ui/infinite/infinite-tag-type-recursion.stderr @@ -9,6 +9,17 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum MList { Cons(isize, Box), Nil } | ++++ + -error: aborting due to 1 previous error +error[E0391]: cycle detected when computing when `MList` needs drop + --> $DIR/infinite-tag-type-recursion.rs:1:1 + | +LL | enum MList { Cons(isize, MList), Nil } + | ^^^^^^^^^^ + | + = note: ...which immediately requires computing when `MList` needs drop again + = note: cycle used when computing whether `MList` needs drop + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs index 06cf8c0f0f6d5..8ea4eac1a6173 100644 --- a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs +++ b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs @@ -26,5 +26,7 @@ fn main() { let _ = A(0); let _ = B(0); let _ = C(0); - let _ = E::X; + unsafe { + let _ = E::X; + } } diff --git a/tests/ui/issues/issue-11374.rs b/tests/ui/issues/issue-11374.rs index 7519ba2826e7a..60ee256c65a90 100644 --- a/tests/ui/issues/issue-11374.rs +++ b/tests/ui/issues/issue-11374.rs @@ -18,6 +18,7 @@ impl<'a> Container<'a> { pub fn for_stdin<'a>() -> Container<'a> { let mut r = io::stdin(); Container::wrap(&mut r as &mut dyn io::Read) + //~^ ERROR cannot return value referencing local variable } fn main() { diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr index 275a0e6b5d775..3ae5cfc79f874 100644 --- a/tests/ui/issues/issue-11374.stderr +++ b/tests/ui/issues/issue-11374.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-11374.rs:26:15 + --> $DIR/issue-11374.rs:27:15 | LL | c.read_to(v); | ------- ^ expected `&mut [u8]`, found `Vec<_>` @@ -18,6 +18,16 @@ help: consider mutably borrowing here LL | c.read_to(&mut v); | ++++ -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing local variable `r` + --> $DIR/issue-11374.rs:20:5 + | +LL | Container::wrap(&mut r as &mut dyn io::Read) + | ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `r` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0515. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13497.rs b/tests/ui/issues/issue-13497.rs index 4b2795aa841e8..7f786a54b9f71 100644 --- a/tests/ui/issues/issue-13497.rs +++ b/tests/ui/issues/issue-13497.rs @@ -3,6 +3,7 @@ fn read_lines_borrowed1() -> Vec< > { let rawLines: Vec = vec!["foo ".to_string(), " bar".to_string()]; rawLines.iter().map(|l| l.trim()).collect() + //~^ ERROR: cannot return value referencing } fn main() {} diff --git a/tests/ui/issues/issue-13497.stderr b/tests/ui/issues/issue-13497.stderr index fb3de637a7985..7630848f6a512 100644 --- a/tests/ui/issues/issue-13497.stderr +++ b/tests/ui/issues/issue-13497.stderr @@ -14,6 +14,16 @@ help: instead, you are more likely to want to return an owned value LL | String | ~~~~~~ -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing local variable `rawLines` + --> $DIR/issue-13497.rs:5:5 + | +LL | rawLines.iter().map(|l| l.trim()).collect() + | --------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `rawLines` is borrowed here + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0515. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/issues/issue-2848.rs b/tests/ui/issues/issue-2848.rs index e0049bf8fbb00..34181acdd0556 100644 --- a/tests/ui/issues/issue-2848.rs +++ b/tests/ui/issues/issue-2848.rs @@ -12,6 +12,7 @@ fn main() { use bar::foo::{alpha, charlie}; match alpha { alpha | beta => {} //~ ERROR variable `beta` is not bound in all patterns + //~^ ERROR: `beta` is named the same as one of the variants charlie => {} } } diff --git a/tests/ui/issues/issue-2848.stderr b/tests/ui/issues/issue-2848.stderr index 873f7efcd73f3..1cef27c34635e 100644 --- a/tests/ui/issues/issue-2848.stderr +++ b/tests/ui/issues/issue-2848.stderr @@ -6,6 +6,15 @@ LL | alpha | beta => {} | | | pattern doesn't bind `beta` -error: aborting due to 1 previous error +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `bar::foo` + --> $DIR/issue-2848.rs:14:15 + | +LL | alpha | beta => {} + | ^^^^ help: to match on the variant, qualify the path: `bar::foo::beta` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0170, E0408. +For more information about an error, try `rustc --explain E0170`. diff --git a/tests/ui/issues/issue-28971.rs b/tests/ui/issues/issue-28971.rs index f0a1e2d006179..8e7a2fe0ef209 100644 --- a/tests/ui/issues/issue-28971.rs +++ b/tests/ui/issues/issue-28971.rs @@ -13,4 +13,5 @@ fn main(){ fn foo(f: F) where F: FnMut() { f(); + //~^ ERROR: cannot borrow } diff --git a/tests/ui/issues/issue-28971.stderr b/tests/ui/issues/issue-28971.stderr index 8fd3c7ffc3035..26057cbc2d1d8 100644 --- a/tests/ui/issues/issue-28971.stderr +++ b/tests/ui/issues/issue-28971.stderr @@ -10,6 +10,18 @@ LL | Foo::Baz(..) => (), | variant or associated item not found in `Foo` | help: there is a variant with a similar name: `Bar` -error: aborting due to 1 previous error +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/issue-28971.rs:15:5 + | +LL | f(); + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo(mut f: F) where F: FnMut() { + | +++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0599`. +Some errors have detailed explanations: E0596, E0599. +For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/kindck/kindck-impl-type-params.rs b/tests/ui/kindck/kindck-impl-type-params.rs index 72a6599c32696..707c5dbaec30e 100644 --- a/tests/ui/kindck/kindck-impl-type-params.rs +++ b/tests/ui/kindck/kindck-impl-type-params.rs @@ -28,6 +28,7 @@ fn g(val: T) { fn foo<'a>() { let t: S<&'a isize> = S(marker::PhantomData); let a = &t as &dyn Gettable<&'a isize>; + //~^ ERROR: lifetime may not live long enough } fn foo2<'a>() { diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index fe03ac422d2d2..aad020e4ec97a 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -75,7 +75,7 @@ LL | fn g(val: T) { | +++++++++++++++++++ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/kindck-impl-type-params.rs:35:13 + --> $DIR/kindck-impl-type-params.rs:36:13 | LL | let a = t as Box>; | ^ the trait `Copy` is not implemented for `String`, which is required by `S: Gettable` @@ -91,7 +91,7 @@ LL | impl Gettable for S {} = note: required for the cast from `Box>` to `Box>` error[E0277]: the trait bound `Foo: Copy` is not satisfied - --> $DIR/kindck-impl-type-params.rs:43:37 + --> $DIR/kindck-impl-type-params.rs:44:37 | LL | let a: Box> = t; | ^ the trait `Copy` is not implemented for `Foo`, which is required by `S: Gettable` @@ -111,6 +111,15 @@ LL + #[derive(Copy)] LL | struct Foo; // does not impl Copy | -error: aborting due to 6 previous errors +error: lifetime may not live long enough + --> $DIR/kindck-impl-type-params.rs:30:13 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let t: S<&'a isize> = S(marker::PhantomData); +LL | let a = &t as &dyn Gettable<&'a isize>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-object1.rs b/tests/ui/kindck/kindck-send-object1.rs index 787d0f8f6cbfb..0ce3995dccc9a 100644 --- a/tests/ui/kindck/kindck-send-object1.rs +++ b/tests/ui/kindck/kindck-send-object1.rs @@ -12,6 +12,7 @@ fn test51<'a>() { } fn test52<'a>() { assert_send::<&'a (dyn Dummy + Sync)>(); + //~^ ERROR: lifetime may not live long enough } // ...unless they are properly bounded diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index 771c54dce0d10..39343b9993b5a 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -13,7 +13,7 @@ LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely - --> $DIR/kindck-send-object1.rs:28:19 + --> $DIR/kindck-send-object1.rs:29:19 | LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely @@ -28,6 +28,14 @@ note: required by a bound in `assert_send` LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` -error: aborting due to 2 previous errors +error: lifetime may not live long enough + --> $DIR/kindck-send-object1.rs:14:5 + | +LL | fn test52<'a>() { + | -- lifetime `'a` defined here +LL | assert_send::<&'a (dyn Dummy + Sync)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lifetimes/issue-17728.rs b/tests/ui/lifetimes/issue-17728.rs index 6aca159c47e34..ff8783029ff52 100644 --- a/tests/ui/lifetimes/issue-17728.rs +++ b/tests/ui/lifetimes/issue-17728.rs @@ -12,7 +12,7 @@ trait TraversesWorld { let direction = str_to_direction(directionStr); let maybe_room = room.direction_to_room.get(&direction); match maybe_room { - Some(entry) => Ok(entry), + Some(entry) => Ok(entry), //~ ERROR: lifetime may not live long enough _ => Err("Direction does not exist in room.") } } diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr index fb1c7cf7ad35b..23547f722a116 100644 --- a/tests/ui/lifetimes/issue-17728.stderr +++ b/tests/ui/lifetimes/issue-17728.stderr @@ -16,6 +16,22 @@ LL | | } = note: expected enum `RoomDirection` found enum `Option<_>` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/issue-17728.rs:15:28 + | +LL | fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +... +LL | Some(entry) => Ok(entry), + | ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter + | +LL | fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> { + | ++++ ++ ++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs index d6c918843c700..56f89b7041085 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs @@ -1,5 +1,7 @@ fn foo(x: &i32, y: &i32) -> &i32 { //~ ERROR missing lifetime if x > y { x } else { y } + //~^ ERROR: lifetime may not live long enough + //~| ERROR: lifetime may not live long enough } fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index 62b0a8a04bf79..db5b039d1c2f0 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -10,6 +10,22 @@ help: consider introducing a named lifetime parameter LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { | ++++ ++ ++ ++ -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/ex1b-return-no-names-if-else.rs:2:16 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | - let's call the lifetime of this reference `'1` +LL | if x > y { x } else { y } + | ^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/ex1b-return-no-names-if-else.rs:2:27 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | - let's call the lifetime of this reference `'2` +LL | if x > y { x } else { y } + | ^ returning this value requires that `'2` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/liveness/liveness-forgot-ret.rs b/tests/ui/liveness/liveness-forgot-ret.rs index b8c2bc7343892..3ba2f2d276ef6 100644 --- a/tests/ui/liveness/liveness-forgot-ret.rs +++ b/tests/ui/liveness/liveness-forgot-ret.rs @@ -1,4 +1,5 @@ fn god_exists(a: isize) -> bool { return god_exists(a); } +//~^ WARN function cannot return without recursing fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } //~^ ERROR mismatched types diff --git a/tests/ui/liveness/liveness-forgot-ret.stderr b/tests/ui/liveness/liveness-forgot-ret.stderr index a5adadca26ee2..f72a30fc4e9c7 100644 --- a/tests/ui/liveness/liveness-forgot-ret.stderr +++ b/tests/ui/liveness/liveness-forgot-ret.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/liveness-forgot-ret.rs:3:19 + --> $DIR/liveness-forgot-ret.rs:4:19 | LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } | - ^^^^^ expected `isize`, found `()` @@ -11,6 +11,17 @@ help: consider returning the local binding `a` LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a } | + -error: aborting due to 1 previous error +warning: function cannot return without recursing + --> $DIR/liveness-forgot-ret.rs:1:1 + | +LL | fn god_exists(a: isize) -> bool { return god_exists(a); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------- recursive call site + | | + | cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/loops/loop-else-break-with-value.rs b/tests/ui/loops/loop-else-break-with-value.rs index 670d8a145c0af..7ccf71b2edf4a 100644 --- a/tests/ui/loops/loop-else-break-with-value.rs +++ b/tests/ui/loops/loop-else-break-with-value.rs @@ -1,6 +1,11 @@ fn main() { let Some(1) = loop { //~^ NOTE `else` is attached to this loop + //~| ERROR refutable pattern in local binding + //~| NOTE not covered + //~| NOTE for more information + //~| NOTE matched value is of type + //~| NOTE require an "irrefutable pattern" break Some(1) } else { //~^ ERROR `loop...else` loops are not supported diff --git a/tests/ui/loops/loop-else-break-with-value.stderr b/tests/ui/loops/loop-else-break-with-value.stderr index c933e0d0cd8ea..13d4c5faf7326 100644 --- a/tests/ui/loops/loop-else-break-with-value.stderr +++ b/tests/ui/loops/loop-else-break-with-value.stderr @@ -1,5 +1,5 @@ error: `loop...else` loops are not supported - --> $DIR/loop-else-break-with-value.rs:5:7 + --> $DIR/loop-else-break-with-value.rs:10:7 | LL | let Some(1) = loop { | ---- `else` is attached to this loop @@ -14,5 +14,24 @@ LL | | }; | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to 1 previous error +error[E0005]: refutable pattern in local binding + --> $DIR/loop-else-break-with-value.rs:2:9 + | +LL | let Some(1) = loop { + | ^^^^^^^ pattern `None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Option` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL ~ if let Some(1) = loop { +LL | + ... +LL | return; +LL ~ } { todo!() }; + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/methods/assign-to-method.rs b/tests/ui/methods/assign-to-method.rs index 71e40759c848b..58dcca77e62cb 100644 --- a/tests/ui/methods/assign-to-method.rs +++ b/tests/ui/methods/assign-to-method.rs @@ -6,7 +6,7 @@ struct Cat { } impl Cat { - pub fn speak(&self) { self.meows += 1; } + pub fn speak(&mut self) { self.meows += 1; } } fn cat(in_x : usize, in_y : isize) -> Cat { diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs index 98abb0ba97951..e73a33dfded7c 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -8,4 +8,7 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { baz(f); + //~^ ERROR: mismatched types + //~| ERROR: borrowed data escapes + //~| ERROR: not general enough } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index e9808b8699186..e63d3f6a075db 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -41,6 +41,52 @@ LL | a.iter().map(|_: (u16, u16)| 45); note: required by a bound in `map` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | -- - `f` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | baz(f); + | ^^^^^^ + | | + | `f` escapes the function body here + | argument requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `&u32` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> Fn(*mut &'a u32)` + found trait `Fn(*mut &u32)` +note: the lifetime requirement is introduced here + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0631`. +Some errors have detailed explanations: E0308, E0521, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/continue-after-missing-main.rs b/tests/ui/nll/continue-after-missing-main.rs index 778639158d7f9..5968364878994 100644 --- a/tests/ui/nll/continue-after-missing-main.rs +++ b/tests/ui/nll/continue-after-missing-main.rs @@ -26,4 +26,6 @@ fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( tableau: Tableau<'data_provider, AdaptedMatrixProvider<'original_data, MP>>, ) { let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + //~^ ERROR: lifetime may not live long enough + //~| ERROR: `tableau` does not live long enough } //~ ERROR `main` function not found in crate diff --git a/tests/ui/nll/continue-after-missing-main.stderr b/tests/ui/nll/continue-after-missing-main.stderr index 960503e8fd5bf..5178d1b7ee25e 100644 --- a/tests/ui/nll/continue-after-missing-main.stderr +++ b/tests/ui/nll/continue-after-missing-main.stderr @@ -1,9 +1,39 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main` - --> $DIR/continue-after-missing-main.rs:29:2 + --> $DIR/continue-after-missing-main.rs:31:2 | LL | } | ^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/continue-after-missing-main.rs:28:12 + | +LL | fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( + | -------------- -------------- lifetime `'original_data` defined here + | | + | lifetime `'data_provider` defined here +... +LL | let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'data_provider` must outlive `'original_data` + | + = help: consider adding the following bound: `'data_provider: 'original_data` + +error[E0597]: `tableau` does not live long enough + --> $DIR/continue-after-missing-main.rs:28:56 + | +LL | fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( + | -------------- lifetime `'original_data` defined here +LL | tableau: Tableau<'data_provider, AdaptedMatrixProvider<'original_data, MP>>, + | ------- binding `tableau` declared here +LL | ) { +LL | let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + | ----------------------------------------- ^^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `tableau` is borrowed for `'original_data` +... +LL | } + | - `tableau` dropped here while still borrowed + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0601`. +Some errors have detailed explanations: E0597, E0601. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/or-patterns/missing-bindings.rs b/tests/ui/or-patterns/missing-bindings.rs index 7c26012c0e93d..20844c17ec1a3 100644 --- a/tests/ui/or-patterns/missing-bindings.rs +++ b/tests/ui/or-patterns/missing-bindings.rs @@ -17,8 +17,10 @@ fn check_handling_of_paths() { use bar::foo::{alpha, charlie}; let (alpha | beta | charlie) = alpha; //~ ERROR variable `beta` is not bound in all patterns - match Some(alpha) { + //~^ ERROR: `beta` is named the same as one of the variants + match Some(alpha) { //~ ERROR `None` not covered Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns + //~^ ERROR: `beta` is named the same as one of the variants } } diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr index 7f182a857871d..677b40a7f0dc1 100644 --- a/tests/ui/or-patterns/missing-bindings.stderr +++ b/tests/ui/or-patterns/missing-bindings.stderr @@ -8,7 +8,7 @@ LL | let (alpha | beta | charlie) = alpha; | pattern doesn't bind `beta` error[E0408]: variable `beta` is not bound in all patterns - --> $DIR/missing-bindings.rs:21:14 + --> $DIR/missing-bindings.rs:22:14 | LL | Some(alpha | beta) => {} | ^^^^^ ---- variable not in all patterns @@ -16,7 +16,7 @@ LL | Some(alpha | beta) => {} | pattern doesn't bind `beta` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:33:20 + --> $DIR/missing-bindings.rs:35:20 | LL | let (A(a, _) | _) = X; | - ^ pattern doesn't bind `a` @@ -24,7 +24,7 @@ LL | let (A(a, _) | _) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:34:10 + --> $DIR/missing-bindings.rs:36:10 | LL | let (_ | B(a)) = X; | ^ - variable not in all patterns @@ -32,7 +32,7 @@ LL | let (_ | B(a)) = X; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:35:10 + --> $DIR/missing-bindings.rs:37:10 | LL | let (A(..) | B(a)) = X; | ^^^^^ - variable not in all patterns @@ -40,7 +40,7 @@ LL | let (A(..) | B(a)) = X; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:36:20 + --> $DIR/missing-bindings.rs:38:20 | LL | let (A(a, _) | B(_)) = X; | - ^^^^ pattern doesn't bind `a` @@ -48,7 +48,7 @@ LL | let (A(a, _) | B(_)) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:37:20 + --> $DIR/missing-bindings.rs:39:20 | LL | let (A(_, a) | B(_)) = X; | - ^^^^ pattern doesn't bind `a` @@ -56,7 +56,7 @@ LL | let (A(_, a) | B(_)) = X; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:38:20 + --> $DIR/missing-bindings.rs:40:20 | LL | let (A(a, b) | B(a)) = X; | - ^^^^ pattern doesn't bind `b` @@ -64,7 +64,7 @@ LL | let (A(a, b) | B(a)) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:42:10 + --> $DIR/missing-bindings.rs:44:10 | LL | let (A(A(..) | B(_), _) | B(a)) = Y; | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns @@ -72,7 +72,7 @@ LL | let (A(A(..) | B(_), _) | B(a)) = Y; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:43:12 + --> $DIR/missing-bindings.rs:45:12 | LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | ^^^^^ - variable not in all patterns @@ -80,7 +80,7 @@ LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | pattern doesn't bind `a` error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:12 + --> $DIR/missing-bindings.rs:47:12 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | ^^^^^^^ - variable not in all patterns @@ -88,7 +88,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | pattern doesn't bind `c` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:22 + --> $DIR/missing-bindings.rs:47:22 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `a` @@ -96,7 +96,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:22 + --> $DIR/missing-bindings.rs:47:22 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `b` @@ -104,7 +104,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `e` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:10 + --> $DIR/missing-bindings.rs:47:10 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns @@ -112,7 +112,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | pattern doesn't bind `e` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `a` @@ -120,7 +120,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `b` @@ -128,7 +128,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `c` @@ -136,7 +136,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `d` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `d` @@ -144,7 +144,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:61:29 + --> $DIR/missing-bindings.rs:63:29 | LL | Ok(a) | Err(_), | - ^^^^^^ pattern doesn't bind `a` @@ -152,7 +152,7 @@ LL | Ok(a) | Err(_), | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:68:21 + --> $DIR/missing-bindings.rs:70:21 | LL | A(_, a) | | ^^^^^^^ pattern doesn't bind `b` @@ -160,7 +160,7 @@ LL | B(b), | - variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:69:21 + --> $DIR/missing-bindings.rs:71:21 | LL | A(_, a) | | - variable not in all patterns @@ -168,7 +168,7 @@ LL | B(b), | ^^^^ pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:72:17 + --> $DIR/missing-bindings.rs:74:17 | LL | A(_, a) | | - variable not in all patterns @@ -177,7 +177,7 @@ LL | B(_) | ^^^^ pattern doesn't bind `a` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:72:17 + --> $DIR/missing-bindings.rs:74:17 | LL | B(b), | - variable not in all patterns @@ -186,7 +186,7 @@ LL | B(_) | ^^^^ pattern doesn't bind `b` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:57:13 + --> $DIR/missing-bindings.rs:59:13 | LL | / V1( LL | | @@ -204,7 +204,7 @@ LL | V3(c), | ^^^^^ pattern doesn't bind `b` error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:57:13 + --> $DIR/missing-bindings.rs:59:13 | LL | / V1( LL | | @@ -226,7 +226,7 @@ LL | V3(c), | - variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:76:13 + --> $DIR/missing-bindings.rs:78:13 | LL | B(Ok(a) | Err(a)) | - variable not in all patterns @@ -237,6 +237,38 @@ LL | A(_, a) | LL | V3(c), | ^^^^^ pattern doesn't bind `a` -error: aborting due to 26 previous errors +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `check_handling_of_paths::bar::foo` + --> $DIR/missing-bindings.rs:19:18 + | +LL | let (alpha | beta | charlie) = alpha; + | ^^^^ + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `check_handling_of_paths::bar::foo` + --> $DIR/missing-bindings.rs:22:22 + | +LL | Some(alpha | beta) => {} + | ^^^^ help: to match on the variant, qualify the path: `check_handling_of_paths::bar::foo::beta` + +error[E0004]: non-exhaustive patterns: `None` not covered + --> $DIR/missing-bindings.rs:21:11 + | +LL | match Some(alpha) { + | ^^^^^^^^^^^ pattern `None` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | Some(alpha | beta) => {}, None => todo!() + | +++++++++++++++++ + +error: aborting due to 29 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0004, E0170, E0408. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index a42e8c41c2efd..c3126a493e546 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -5,6 +5,7 @@ fn a() { let foo = { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -23,6 +24,7 @@ fn b() { fn c() { let foo = if true { + //~^ WARN irrefutable `let...else` pattern 1 } else { 0 @@ -43,6 +45,7 @@ fn d() { fn e() { let foo = match true { + //~^ WARN irrefutable `let...else` pattern true => 1, false => 0 } else { @@ -54,6 +57,7 @@ fn e() { struct X {a: i32} fn f() { let foo = X { + //~^ WARN irrefutable `let...else` pattern a: 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -72,6 +76,7 @@ fn g() { fn h() { let foo = const { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -81,6 +86,7 @@ fn h() { fn i() { let foo = &{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -90,7 +96,8 @@ fn i() { fn j() { let bar = 0; - let foo = bar = { + let foo = bar = { //~ ERROR: cannot assign twice + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -100,6 +107,7 @@ fn j() { fn k() { let foo = 1 + { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -109,6 +117,7 @@ fn k() { fn l() { let foo = 1..{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -118,6 +127,7 @@ fn l() { fn m() { let foo = return { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -127,6 +137,7 @@ fn m() { fn n() { let foo = -{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -136,6 +147,7 @@ fn n() { fn o() -> Result<(), ()> { let foo = do yeet { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -145,6 +157,7 @@ fn o() -> Result<(), ()> { fn p() { let foo = become { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -154,6 +167,7 @@ fn p() { fn q() { let foo = |x: i32| { + //~^ WARN irrefutable `let...else` pattern x } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -163,14 +177,18 @@ fn q() { fn r() { let ok = format_args!("") else { return; }; + //~^ WARN irrefutable `let...else` pattern let bad = format_args! {""} else { return; }; //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~| WARN irrefutable `let...else` pattern } fn s() { macro_rules! a { () => { {} } + //~^ WARN irrefutable `let...else` pattern + //~| WARN irrefutable `let...else` pattern } macro_rules! b { diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 887455913d84a..12df8f849abd2 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -1,5 +1,5 @@ error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:9:5 + --> $DIR/bad-let-else-statement.rs:10:5 | LL | } else { | ^ @@ -7,12 +7,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = ({ +LL | LL | 1 LL ~ }) else { | error: `for...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:18:7 + --> $DIR/bad-let-else-statement.rs:19:7 | LL | let foo = for i in 1..2 { | --- `else` is attached to this loop @@ -27,7 +28,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:29:5 + --> $DIR/bad-let-else-statement.rs:31:5 | LL | } else { | ^ @@ -35,14 +36,14 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (if true { -LL | 1 -LL | } else { +LL | + ... LL | 0 LL ~ }) else { | error: `loop...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:38:7 + --> $DIR/bad-let-else-statement.rs:40:7 | LL | let foo = loop { | ---- `else` is attached to this loop @@ -57,7 +58,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:48:5 + --> $DIR/bad-let-else-statement.rs:51:5 | LL | } else { | ^ @@ -65,13 +66,14 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (match true { +LL | LL | true => 1, LL | false => 0 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:58:5 + --> $DIR/bad-let-else-statement.rs:62:5 | LL | } else { | ^ @@ -79,12 +81,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (X { +LL | LL | a: 1 LL ~ }) else { | error: `while...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:67:7 + --> $DIR/bad-let-else-statement.rs:71:7 | LL | let foo = while false { | ----- `else` is attached to this loop @@ -99,7 +102,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:76:5 + --> $DIR/bad-let-else-statement.rs:81:5 | LL | } else { | ^ @@ -107,12 +110,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (const { +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:85:5 + --> $DIR/bad-let-else-statement.rs:91:5 | LL | } else { | ^ @@ -120,12 +124,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = &({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:95:5 + --> $DIR/bad-let-else-statement.rs:102:5 | LL | } else { | ^ @@ -133,12 +138,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = bar = ({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:104:5 + --> $DIR/bad-let-else-statement.rs:112:5 | LL | } else { | ^ @@ -146,12 +152,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = 1 + ({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:113:5 + --> $DIR/bad-let-else-statement.rs:122:5 | LL | } else { | ^ @@ -159,12 +166,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = 1..({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:122:5 + --> $DIR/bad-let-else-statement.rs:132:5 | LL | } else { | ^ @@ -172,12 +180,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = return ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:131:5 + --> $DIR/bad-let-else-statement.rs:142:5 | LL | } else { | ^ @@ -185,12 +194,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = -({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:140:5 + --> $DIR/bad-let-else-statement.rs:152:5 | LL | } else { | ^ @@ -198,12 +208,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = do yeet ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:149:5 + --> $DIR/bad-let-else-statement.rs:162:5 | LL | } else { | ^ @@ -211,12 +222,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = become ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:158:5 + --> $DIR/bad-let-else-statement.rs:172:5 | LL | } else { | ^ @@ -224,12 +236,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = |x: i32| ({ +LL | LL | x LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:167:31 + --> $DIR/bad-let-else-statement.rs:182:31 | LL | let bad = format_args! {""} else { return; }; | ^ @@ -240,7 +253,7 @@ LL | let bad = format_args! ("") else { return; }; | ~ ~ error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:181:25 + --> $DIR/bad-let-else-statement.rs:199:25 | LL | let x = a! {} else { return; }; | ^ @@ -254,5 +267,251 @@ help: use parentheses instead of braces for this macro LL | let x = a! () else { return; }; | ~~ -error: aborting due to 19 previous errors +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:7:5 + | +LL | / let foo = { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: `#[warn(irrefutable_let_patterns)]` on by default + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:26:5 + | +LL | / let foo = if true { +LL | | +LL | | 1 +LL | | } else { +LL | | 0 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:47:5 + | +LL | / let foo = match true { +LL | | +LL | | true => 1, +LL | | false => 0 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:59:5 + | +LL | / let foo = X { +LL | | +LL | | a: 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:78:5 + | +LL | / let foo = const { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:88:5 + | +LL | / let foo = &{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:99:5 + | +LL | / let foo = bar = { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +error[E0384]: cannot assign twice to immutable variable `bar` + --> $DIR/bad-let-else-statement.rs:99:15 + | +LL | let bar = 0; + | --- + | | + | first assignment to `bar` + | help: consider making this binding mutable: `mut bar` +LL | let foo = bar = { + | _______________^ +LL | | +LL | | 1 +LL | | } else { + | |_____^ cannot assign twice to immutable variable + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:109:5 + | +LL | / let foo = 1 + { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:119:5 + | +LL | / let foo = 1..{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:129:5 + | +LL | / let foo = return { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:139:5 + | +LL | / let foo = -{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:149:5 + | +LL | / let foo = do yeet { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:159:5 + | +LL | / let foo = become { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:169:5 + | +LL | / let foo = |x: i32| { +LL | | +LL | | x +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:179:5 + | +LL | let ok = format_args!("") else { return; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:182:5 + | +LL | let bad = format_args! {""} else { return; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:189:19 + | +LL | () => { {} } + | ___________________^ +LL | | +LL | | +LL | | } +... | +LL | | (1) => { +LL | | let x = a!() else { return; }; + | |____________^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:189:19 + | +LL | () => { {} } + | ___________________^ +LL | | +LL | | +LL | | } +... | +LL | | (2) => { +LL | | let x = a! {} else { return; }; + | |____________^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 20 previous errors; 18 warnings emitted +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs b/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs index 3d110adef3e34..c1c847d92d04b 100644 --- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs @@ -129,6 +129,7 @@ pub fn inside_block() { static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); //~^ ERROR: cast cannot be followed by indexing +//~| ERROR: cannot call non-const operator in statics static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); //~^ ERROR: expected one of diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr index d313c888e51c6..6a8cbd9389b76 100644 --- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr @@ -235,13 +235,13 @@ LL | static bar: &[i32] = &((&[1,2,3] as &[i32])[0..1]); | + + error: expected one of `)`, `,`, `.`, `?`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:133:36 + --> $DIR/issue-35813-postfix-after-cast.rs:134:36 | LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); | ^ expected one of `)`, `,`, `.`, `?`, or an operator error: cast cannot be followed by `?` - --> $DIR/issue-35813-postfix-after-cast.rs:138:5 + --> $DIR/issue-35813-postfix-after-cast.rs:139:5 | LL | Err(0u64) as Result?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -252,13 +252,13 @@ LL | (Err(0u64) as Result)?; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:140:14 + --> $DIR/issue-35813-postfix-after-cast.rs:141:14 | LL | Err(0u64): Result?; | ^ expected one of `.`, `;`, `?`, `}`, or an operator error: expected identifier, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:152:13 + --> $DIR/issue-35813-postfix-after-cast.rs:153:13 | LL | drop_ptr: F(); | ^ expected identifier @@ -266,13 +266,13 @@ LL | drop_ptr: F(); = note: type ascription syntax has been removed, see issue #101728 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:159:13 + --> $DIR/issue-35813-postfix-after-cast.rs:160:13 | LL | drop_ptr: fn(u8); | ^ expected one of 8 possible tokens error: cast cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:165:5 + --> $DIR/issue-35813-postfix-after-cast.rs:166:5 | LL | drop as fn(u8)(0); | ^^^^^^^^^^^^^^ @@ -283,13 +283,13 @@ LL | (drop as fn(u8))(0); | + + error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:167:13 + --> $DIR/issue-35813-postfix-after-cast.rs:168:13 | LL | drop_ptr: fn(u8)(0); | ^ expected one of 8 possible tokens error: cast cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:172:5 + --> $DIR/issue-35813-postfix-after-cast.rs:173:5 | LL | Box::pin(noop()) as Pin>>.await; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -300,13 +300,13 @@ LL | (Box::pin(noop()) as Pin>>).await; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:175:21 + --> $DIR/issue-35813-postfix-after-cast.rs:176:21 | LL | Box::pin(noop()): Pin>.await; | ^ expected one of `.`, `;`, `?`, `}`, or an operator error: cast cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:187:5 + --> $DIR/issue-35813-postfix-after-cast.rs:188:5 | LL | Foo::default() as Foo.bar; | ^^^^^^^^^^^^^^^^^^^^^ @@ -317,7 +317,7 @@ LL | (Foo::default() as Foo).bar; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:189:19 + --> $DIR/issue-35813-postfix-after-cast.rs:190:19 | LL | Foo::default(): Foo.bar; | ^ expected one of `.`, `;`, `?`, `}`, or an operator @@ -340,11 +340,22 @@ LL | if true { 33 } else { 44 }: i32.max(0) | ^ expected one of `,`, `.`, `?`, or an operator error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:150:13 + --> $DIR/issue-35813-postfix-after-cast.rs:151:13 | LL | drop as F(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 39 previous errors +error[E0015]: cannot call non-const operator in statics + --> $DIR/issue-35813-postfix-after-cast.rs:130:42 + | +LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); + | ^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error: aborting due to 40 previous errors -For more information about this error, try `rustc --explain E0214`. +Some errors have detailed explanations: E0015, E0214. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs index e1ea38f2795df..d081c06044f14 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -37,9 +37,10 @@ fn g1() { //~| HELP: maybe write a path separator here _ => {} } - if let Foo:Bar = f() { + if let Foo:Bar = f() { //~ WARN: irrefutable `if let` pattern //~^ ERROR: expected one of //~| HELP: maybe write a path separator here + //~| HELP: consider replacing the `if let` with a `let` } } diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr index 63b072ac4cdc6..b6e24faf5dabb 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -64,7 +64,7 @@ LL | if let Foo::Bar = f() { | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:48:16 + --> $DIR/issue-87086-colon-path-sep.rs:49:16 | LL | ref qux: Foo::Baz => {} | ^ -------- specifying the type of a pattern isn't supported @@ -77,7 +77,7 @@ LL | ref qux::Foo::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:57:16 + --> $DIR/issue-87086-colon-path-sep.rs:58:16 | LL | mut qux: Foo::Baz => {} | ^ -------- specifying the type of a pattern isn't supported @@ -90,7 +90,7 @@ LL | mut qux::Foo::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:68:12 + --> $DIR/issue-87086-colon-path-sep.rs:69:12 | LL | Foo:Bar::Baz => {} | ^-------- specifying the type of a pattern isn't supported @@ -103,7 +103,7 @@ LL | Foo::Bar::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:74:12 + --> $DIR/issue-87086-colon-path-sep.rs:75:12 | LL | Foo:Bar => {} | ^--- specifying the type of a pattern isn't supported @@ -115,5 +115,15 @@ help: maybe write a path separator here LL | Foo::Bar => {} | ~~ -error: aborting due to 9 previous errors +warning: irrefutable `if let` pattern + --> $DIR/issue-87086-colon-path-sep.rs:40:8 + | +LL | if let Foo:Bar = f() { + | ^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default + +error: aborting due to 9 previous errors; 1 warning emitted diff --git a/tests/ui/parser/recover/recover-range-pats.rs b/tests/ui/parser/recover/recover-range-pats.rs index 156c7ad94d36a..3dc525cd6e104 100644 --- a/tests/ui/parser/recover/recover-range-pats.rs +++ b/tests/ui/parser/recover/recover-range-pats.rs @@ -134,10 +134,13 @@ fn with_macro_expr_var() { macro_rules! mac2 { ($e1:expr, $e2:expr) => { let $e1..$e2; + //~^ ERROR refutable pattern in local binding let $e1...$e2; //~^ ERROR `...` range patterns are deprecated //~| WARN this is accepted in the current edition + //~| ERROR refutable pattern in local binding let $e1..=$e2; + //~^ ERROR refutable pattern in local binding } } @@ -146,12 +149,18 @@ fn with_macro_expr_var() { macro_rules! mac { ($e:expr) => { let ..$e; + //~^ ERROR refutable pattern in local binding let ...$e; //~^ ERROR range-to patterns with `...` are not allowed + //~| ERROR refutable pattern in local binding let ..=$e; + //~^ ERROR refutable pattern in local binding let $e..; + //~^ ERROR refutable pattern in local binding let $e...; //~ ERROR inclusive range with no end + //~^ ERROR refutable pattern in local binding let $e..=; //~ ERROR inclusive range with no end + //~^ ERROR refutable pattern in local binding } } diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr index 5b69ca5cd6dfa..7c5cc4777b6b4 100644 --- a/tests/ui/parser/recover/recover-range-pats.stderr +++ b/tests/ui/parser/recover/recover-range-pats.stderr @@ -159,7 +159,7 @@ LL | if let ....3 = 0 {} | ^^^ help: use `..=` instead error: range-to patterns with `...` are not allowed - --> $DIR/recover-range-pats.rs:149:17 + --> $DIR/recover-range-pats.rs:153:17 | LL | let ...$e; | ^^^ help: use `..=` instead @@ -170,7 +170,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/recover-range-pats.rs:153:19 + --> $DIR/recover-range-pats.rs:160:19 | LL | let $e...; | ^^^ help: use `..` instead @@ -182,7 +182,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/recover-range-pats.rs:154:19 + --> $DIR/recover-range-pats.rs:162:19 | LL | let $e..=; | ^^^ help: use `..` instead @@ -271,7 +271,7 @@ LL | if let X... .0 = 0 {} = note: for more information, see error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:137:20 + --> $DIR/recover-range-pats.rs:138:20 | LL | let $e1...$e2; | ^^^ help: use `..=` for an inclusive range @@ -478,7 +478,169 @@ LL | if let ....3 = 0 {} | | | expected integer, found floating-point number -error: aborting due to 60 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:136:17 + | +LL | let $e1..$e2; + | ^^^^^^^^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1..$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:138:17 + | +LL | let $e1...$e2; + | ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1...$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:142:17 + | +LL | let $e1..=$e2; + | ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1..=$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:151:17 + | +LL | let ..$e; + | ^^^^ pattern `0_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ..$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:153:17 + | +LL | let ...$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ...$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:156:17 + | +LL | let ..=$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ..=$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:158:17 + | +LL | let $e..; + | ^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:160:17 + | +LL | let $e...; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e...; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:162:17 + | +LL | let $e..=; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..=; { todo!() } + | ++ +++++++++++ + +error: aborting due to 69 previous errors -Some errors have detailed explanations: E0029, E0308, E0586. -For more information about an error, try `rustc --explain E0029`. +Some errors have detailed explanations: E0005, E0029, E0308, E0586. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs index b173e23e7a183..a2d2388ff5088 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -34,10 +34,12 @@ extern "C" fn f3_3(..., x: isize) {} const unsafe extern "C" fn f4_1(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic +//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time const extern "C" fn f4_2(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time const extern "C" fn f4_3(..., x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic @@ -48,7 +50,7 @@ extern "C" { fn e_f1(...); //~^ ERROR C-variadic function must be declared with at least one named argument fn e_f2(..., x: isize); -//~^ ERROR `...` must be the last argument of a C-variadic function + //~^ ERROR `...` must be the last argument of a C-variadic function } struct X; @@ -68,6 +70,7 @@ impl X { const fn i_f5(x: isize, ...) {} //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR functions cannot be both `const` and C-variadic + //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time } trait T { diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr index 18526080e4cb7..6a65ed79d4fbc 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -83,25 +83,25 @@ LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} | ^^^^^ `const` because of this ^^^ C-variadic because of this error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:38:1 + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:1 | LL | const extern "C" fn f4_2(x: isize, ...) {} | ^^^^^ `const` because of this ^^^ C-variadic because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:38:36 + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:36 | LL | const extern "C" fn f4_2(x: isize, ...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:26 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^ error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:1 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:1 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^^^ ^^^ ^^^ C-variadic because of this @@ -110,67 +110,67 @@ LL | const extern "C" fn f4_3(..., x: isize, ...) {} | `const` because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:26 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^ ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:48:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 | LL | fn e_f1(...); | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:52:13 | LL | fn e_f2(..., x: isize); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:57:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:59:23 | LL | fn i_f1(x: isize, ...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | LL | fn i_f2(...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | LL | fn i_f2(...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 | LL | fn i_f3(..., x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 | LL | fn i_f3(..., x: isize, ...) {} | ^^^ ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 | LL | fn i_f4(..., x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 | LL | fn i_f4(..., x: isize, ...) {} | ^^^ ^^^ error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:68:5 + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:5 | LL | const fn i_f5(x: isize, ...) {} | ^^^^^ ^^^ C-variadic because of this @@ -178,70 +178,95 @@ LL | const fn i_f5(x: isize, ...) {} | `const` because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:68:29 + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:29 | LL | const fn i_f5(x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:74:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:77:23 | LL | fn t_f1(x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:76:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:79:23 | LL | fn t_f2(x: isize, ...); | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 | LL | fn t_f3(...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 | LL | fn t_f3(...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 | LL | fn t_f4(...); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 | LL | fn t_f4(...); | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 | LL | fn t_f5(..., x: isize) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 | LL | fn t_f5(..., x: isize) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:90:13 | LL | fn t_f6(..., x: isize); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:90:13 | LL | fn t_f6(..., x: isize); | ^^^ -error: aborting due to 40 previous errors +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:35:43 + | +LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:36 + | +LL | const extern "C" fn f4_2(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:29 + | +LL | const fn i_f5(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 43 previous errors +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs index f167a3952ee9c..f0f512bef529d 100644 --- a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs @@ -10,7 +10,7 @@ fn main() { match Ok(0) { Ok(a @ b @ a) //~^ ERROR identifier `a` is bound more than once in the same pattern - | Err(a @ b @ a) + | Err(a @ b @ a) //~ ERROR cannot assign twice to immutable variable `a` //~^ ERROR identifier `a` is bound more than once in the same pattern => {} } @@ -20,7 +20,7 @@ fn main() { //~| ERROR identifier `a` is bound more than once in the same pattern let ref a @ ref a = (); //~^ ERROR identifier `a` is bound more than once in the same pattern - let ref mut a @ ref mut a = (); + let ref mut a @ ref mut a = (); //~ ERROR cannot borrow value as mutable more than once at a time //~^ ERROR identifier `a` is bound more than once in the same pattern let a @ (Ok(a) | Err(a)) = Ok(()); diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr index a165549f6b436..e25c30cd4926a 100644 --- a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr @@ -58,7 +58,27 @@ error[E0416]: identifier `a` is bound more than once in the same pattern LL | let a @ (Ok(a) | Err(a)) = Ok(()); | ^ used in a pattern more than once -error: aborting due to 10 previous errors +error: cannot borrow value as mutable more than once at a time + --> $DIR/pat-at-same-name-both.rs:23:9 + | +LL | let ref mut a @ ref mut a = (); + | ^^^^^^^^^ --------- value is mutably borrowed by `a` here + | | + | value is mutably borrowed by `a` here + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/pat-at-same-name-both.rs:13:15 + | +LL | Ok(a @ b @ a) + | - + | | + | first assignment to `a` + | help: consider making this binding mutable: `mut a` +LL | +LL | | Err(a @ b @ a) + | ^ cannot assign twice to immutable variable + +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0415, E0416. -For more information about an error, try `rustc --explain E0415`. +Some errors have detailed explanations: E0384, E0415, E0416. +For more information about an error, try `rustc --explain E0384`. diff --git a/tests/ui/pattern/pattern-binding-disambiguation.rs b/tests/ui/pattern/pattern-binding-disambiguation.rs index ce1d8c6c047b1..8be70f65d0e84 100644 --- a/tests/ui/pattern/pattern-binding-disambiguation.rs +++ b/tests/ui/pattern/pattern-binding-disambiguation.rs @@ -26,7 +26,7 @@ fn main() { match doesnt_matter { BracedStruct => {} // OK, `BracedStruct` is a fresh binding } - match UnitVariant { + match UnitVariant { //~ ERROR: `E::TupleVariant` and `E::BracedVariant { }` not covered UnitVariant => {} // OK, `UnitVariant` is a unit variant pattern } match doesnt_matter { @@ -48,7 +48,7 @@ fn main() { let UnitStruct = UnitStruct; // OK, `UnitStruct` is a unit struct pattern let TupleStruct = doesnt_matter; //~ ERROR let bindings cannot shadow tuple structs let BracedStruct = doesnt_matter; // OK, `BracedStruct` is a fresh binding - let UnitVariant = UnitVariant; // OK, `UnitVariant` is a unit variant pattern + let UnitVariant = UnitVariant; //~ ERROR: refutable pattern in local binding let TupleVariant = doesnt_matter; //~ ERROR let bindings cannot shadow tuple variants let BracedVariant = doesnt_matter; // OK, `BracedVariant` is a fresh binding let CONST = CONST; // OK, `CONST` is a const pattern diff --git a/tests/ui/pattern/pattern-binding-disambiguation.stderr b/tests/ui/pattern/pattern-binding-disambiguation.stderr index d54467b3c0c08..61c32b6a17bdf 100644 --- a/tests/ui/pattern/pattern-binding-disambiguation.stderr +++ b/tests/ui/pattern/pattern-binding-disambiguation.stderr @@ -58,6 +58,53 @@ LL | static STATIC: () = (); LL | let STATIC = doesnt_matter; | ^^^^^^ cannot be named the same as a static -error: aborting due to 6 previous errors +error[E0004]: non-exhaustive patterns: `E::TupleVariant` and `E::BracedVariant { }` not covered + --> $DIR/pattern-binding-disambiguation.rs:29:11 + | +LL | match UnitVariant { + | ^^^^^^^^^^^ patterns `E::TupleVariant` and `E::BracedVariant { }` not covered + | +note: `E` defined here + --> $DIR/pattern-binding-disambiguation.rs:5:6 + | +LL | enum E { + | ^ +LL | UnitVariant, +LL | TupleVariant(), + | ------------ not covered +LL | BracedVariant{}, + | ------------- not covered + = note: the matched value is of type `E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL | UnitVariant => {}, E::TupleVariant | E::BracedVariant { } => todo!() // OK, `UnitVariant` is a unit variant pattern + | ++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/pattern-binding-disambiguation.rs:51:9 + | +LL | let UnitVariant = UnitVariant; + | ^^^^^^^^^^^ patterns `E::TupleVariant` and `E::BracedVariant { }` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/pattern-binding-disambiguation.rs:5:6 + | +LL | enum E { + | ^ +LL | UnitVariant, +LL | TupleVariant(), + | ------------ not covered +LL | BracedVariant{}, + | ------------- not covered + = note: the matched value is of type `E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let UnitVariant = UnitVariant { todo!() }; + | ++ +++++++++++ + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0530`. +Some errors have detailed explanations: E0004, E0005, E0530. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs index d364c467714ce..2aa390bfd39f9 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs @@ -5,13 +5,13 @@ fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a { fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough } fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y); + a(x, y); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index d8269514befd9..5a02d01b4e1ca 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs index 60dafdd528cf2..baf1693b0ccdf 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -6,14 +6,14 @@ fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough *z = *y; } fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y, z); + a(x, y, z); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index e383f352b9e97..063ff46bb6c47 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)` found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 + | +LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5 + | +LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y, z); + | ^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.rs b/tests/ui/regions/regions-lifetime-bounds-on-fns.rs index 177f52fa72d55..c7b7b52d50d0a 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.rs +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.rs @@ -5,13 +5,13 @@ fn a<'a, 'b:'a>(x: &mut &'a isize, y: &mut &'b isize) { fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough } fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y); + a(x, y); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr index 989e91c702b83..830a61a21f9da 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs index 2490909b6a5a9..715f5874b2cc2 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs @@ -3,8 +3,9 @@ fn main() {} fn attr_in_guard() { match None:: { Some(!) //~ ERROR `!` patterns are experimental + //~^ ERROR: mismatched types if #[deny(unused_mut)] //~ ERROR attributes on expressions are experimental false //~ ERROR a guard on a never pattern will never be run } - match false {} + match false {} //~ ERROR: `bool` is non-empty } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr index a456b686e56e3..f16f5e5be8734 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:6:16 + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:7:16 | LL | if #[deny(unused_mut)] | ^^^^^^^^^^^^^^^^^^^ @@ -19,11 +19,34 @@ LL | Some(!) = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: a guard on a never pattern will never be run - --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:7:13 + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:8:13 | LL | false | ^^^^^ help: remove this guard -error: aborting due to 3 previous errors +error: mismatched types + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:5:14 + | +LL | Some(!) + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `u32` + +error[E0004]: non-exhaustive patterns: type `bool` is non-empty + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:10:11 + | +LL | match false {} + | ^^^^^ + | + = note: the matched value is of type `bool` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match false { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0004, E0658. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs index f2e238ecb136a..11489ccaacd36 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs @@ -1,6 +1,7 @@ #![feature(never_patterns)] #![allow(incomplete_features)] +#[derive(Copy, Clone)] enum Void {} fn main() { diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr index b69ba80af88ea..d9c0f67335cdc 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr @@ -1,47 +1,47 @@ error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:16:15 + --> $DIR/bindings.rs:17:15 | LL | Err(&(_a, _b, !)), | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:16:19 + --> $DIR/bindings.rs:17:19 | LL | Err(&(_a, _b, !)), | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:21:25 + --> $DIR/bindings.rs:22:25 | LL | Ok(_ok) | Err(&(_a, _b, !)) => {} | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:21:29 + --> $DIR/bindings.rs:22:29 | LL | Ok(_ok) | Err(&(_a, _b, !)) => {} | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:34:10 + --> $DIR/bindings.rs:35:10 | LL | let (_a, (! | !)) = (true, void); | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:38:9 + --> $DIR/bindings.rs:39:9 | LL | let _a @ ! = void; | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:41:10 + --> $DIR/bindings.rs:42:10 | LL | let (_a @ (), !) = ((), void); | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:44:14 + --> $DIR/bindings.rs:45:14 | LL | (_b @ (_, !))) = (true, void); | ^^ help: use a wildcard `_` instead diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs index e298112244a22..b6da0c20e0778 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs @@ -15,18 +15,18 @@ fn no_arms_or_guards(x: Void) { //~^ ERROR a never pattern is always unreachable None => {} } - match None:: { + match None:: { //~ ERROR: `Some(_)` not covered Some(!) if true, //~^ ERROR guard on a never pattern None => {} } - match None:: { + match None:: { //~ ERROR: `Some(_)` not covered Some(!) if true => {} //~^ ERROR a never pattern is always unreachable None => {} } match None:: { - Some(never!()) => {}, + Some(never!()) => {} //~^ ERROR a never pattern is always unreachable None => {} } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr index bfbc7a1b5340c..5497252890f70 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr @@ -25,11 +25,48 @@ LL | Some(!) if true => {} error: a never pattern is always unreachable --> $DIR/check.rs:29:27 | -LL | Some(never!()) => {}, +LL | Some(never!()) => {} | ^^ | | | this will never be executed | help: remove this expression -error: aborting due to 4 previous errors +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/check.rs:18:11 + | +LL | match None:: { + | ^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/check.rs:23:11 + | +LL | match None:: { + | ^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs index 43e33cbb12061..351438a54707a 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs @@ -7,7 +7,9 @@ use std::arch::asm; //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn f() { - asm!("", options(noreturn)); + unsafe { + asm!("", options(noreturn)); + } } struct S; @@ -17,7 +19,9 @@ impl S { //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn g() { - asm!("", options(noreturn)); + unsafe { + asm!("", options(noreturn)); + } } } diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr index 3f7d0df42a00a..04c5c649d7fd8 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr @@ -5,7 +5,7 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0736]: cannot use `#[track_caller]` with `#[naked]` - --> $DIR/error-with-naked.rs:16:5 + --> $DIR/error-with-naked.rs:18:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/error-with-naked.rs:16:5 + --> $DIR/error-with-naked.rs:18:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs index 1374ad935a388..a032a2ca05232 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -12,7 +12,7 @@ fn call(f: impl Fn()) { f() } -fn call_mut(f: impl FnMut()) { +fn call_mut(mut f: impl FnMut()) { f() } diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 100f2048269dc..67bfaa4c98c79 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -27,10 +27,10 @@ LL | call_mut(foo); = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:15:21 + --> $DIR/fn-traits.rs:15:25 | -LL | fn call_mut(f: impl FnMut()) { - | ^^^^^^^ required by this bound in `call_mut` +LL | fn call_mut(mut f: impl FnMut()) { + | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce()` closure, found `fn() {foo}` --> $DIR/fn-traits.rs:26:15 @@ -80,10 +80,10 @@ LL | call_mut(foo_unsafe); = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:15:21 + --> $DIR/fn-traits.rs:15:25 | -LL | fn call_mut(f: impl FnMut()) { - | ^^^^^^^ required by this bound in `call_mut` +LL | fn call_mut(mut f: impl FnMut()) { + | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce()` closure, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:32:15 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index d70b0d66177eb..14c41f3e01d6f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -4,5 +4,19 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn need_const_closure i32>(x: T) -> i32 { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method-fail.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr index 1642de78692b7..8fe11fffbf9f8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -4,5 +4,19 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn need_const_closure i32>(x: T) -> i32 { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr index 2e448c64d7a40..b66b27ad2bdd5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr @@ -22,5 +22,45 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn answer u8>(f: &F) -> u8 { | ^^^^^^^^^^ -error: aborting due to 4 previous errors +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:12:5 + | +LL | f() * 7 + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>, + | +++++++++++++++++++++++++ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:5 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { + | +++++++++++++++++++++++++ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:11 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { + | +++++++++++++++++++++++++ + +error: aborting due to 7 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs index b3977e6cede0f..2468d51cfdd17 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs @@ -30,8 +30,7 @@ fn non_const_context() { #[unstable(feature = "none", issue = "none")] const fn const_context() { Unstable::func(); - // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is - // not const-stable. + //[stable]~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn // ^ fails, because the `foo` feature is not active @@ -42,8 +41,7 @@ const fn const_context() { pub const fn const_context_not_const_stable() { //[stable]~^ ERROR function has missing const stability attribute Unstable::func(); - // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is - // not const-stable. + //[stable]~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn // ^ fails, because the `foo` feature is not active @@ -53,7 +51,7 @@ pub const fn const_context_not_const_stable() { #[rustc_const_stable(feature = "cheese", since = "1.0.0")] const fn stable_const_context() { Unstable::func(); - //[unstable]~^ ERROR not yet stable as a const fn + //~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn const_context_not_const_stable() diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr index a1aca762ef479..9512953977003 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -10,16 +10,40 @@ LL | | } = note: see issue #67792 for more information error: function has missing const stability attribute - --> $DIR/staged-api.rs:42:1 + --> $DIR/staged-api.rs:41:1 | LL | / pub const fn const_context_not_const_stable() { LL | | LL | | Unstable::func(); -LL | | // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is +LL | | ... | LL | | // ^ fails, because the `foo` feature is not active LL | | } | |_^ -error: aborting due to 2 previous errors +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:32:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:43:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:53:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr index c38d1a81ae77b..c9ca15d5b565f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -1,5 +1,5 @@ error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:35:5 + --> $DIR/staged-api.rs:34:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:47:5 + --> $DIR/staged-api.rs:45:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:55:5 + --> $DIR/staged-api.rs:53:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | Unstable::func(); = help: const-stable functions can only call other const-stable functions error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:57:5 + --> $DIR/staged-api.rs:55:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | Foo::func(); = help: const-stable functions can only call other const-stable functions error: `const_context_not_const_stable` is not yet stable as a const fn - --> $DIR/staged-api.rs:59:5 + --> $DIR/staged-api.rs:57:5 | LL | const_context_not_const_stable() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr index bf53b995bb673..e51ff1483390c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr @@ -4,6 +4,16 @@ error[E0635]: unknown feature `const_default_impls` LL | #![cfg_attr(gated, feature(const_trait_impl, const_default_impls))] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const fn ` as Default>::default` in constant functions + --> $DIR/std-impl-gate.rs:13:5 + | +LL | Default::default() + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/span/issue-23827.rs b/tests/ui/span/issue-23827.rs index 6b065bf6cbff2..81037771389dd 100644 --- a/tests/ui/span/issue-23827.rs +++ b/tests/ui/span/issue-23827.rs @@ -2,6 +2,7 @@ #![feature(fn_traits, unboxed_closures)] +#[derive(Copy, Clone)] pub struct Prototype { pub target: u32 } diff --git a/tests/ui/span/issue-23827.stderr b/tests/ui/span/issue-23827.stderr index fe7c7794c9c7a..56f449ab08bf5 100644 --- a/tests/ui/span/issue-23827.stderr +++ b/tests/ui/span/issue-23827.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `Output` - --> $DIR/issue-23827.rs:26:1 + --> $DIR/issue-23827.rs:27:1 | LL | impl FnOnce<(C,)> for Prototype { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation diff --git a/tests/ui/span/issue-39698.rs b/tests/ui/span/issue-39698.rs index 1079bae2c06ae..9799e67e52137 100644 --- a/tests/ui/span/issue-39698.rs +++ b/tests/ui/span/issue-39698.rs @@ -12,5 +12,6 @@ fn main() { //~| ERROR is not bound in all patterns //~| ERROR is not bound in all patterns //~| ERROR is not bound in all patterns + //~| ERROR `a` is possibly-uninitialized } } diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr index 500080832111b..73fcc5c847755 100644 --- a/tests/ui/span/issue-39698.stderr +++ b/tests/ui/span/issue-39698.stderr @@ -38,6 +38,19 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?} | | variable not in all patterns | variable not in all patterns -error: aborting due to 4 previous errors +error[E0381]: used binding `a` is possibly-uninitialized + --> $DIR/issue-39698.rs:10:79 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | - - ^ `a` used here but it is possibly-uninitialized + | | | + | | binding initialized here in some conditions + | binding initialized here in some conditions + | binding declared here but left uninitialized + | + = 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) + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0381, E0408. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index 913d51875cd70..187049e623cc7 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -16,5 +16,33 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | impl const A for T { | ^^^^^^^ -error: aborting due to 3 previous errors +error[E0015]: cannot call non-const fn `<() as A>::a` in constants + --> $DIR/const_trait_impl.rs:52:23 + | +LL | const _: () = assert!(<()>::a() == 42); + | ^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn `::a` in constants + --> $DIR/const_trait_impl.rs:53:23 + | +LL | const _: () = assert!(::a() == 3); + | ^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn `::a` in constants + --> $DIR/const_trait_impl.rs:54:23 + | +LL | const _: () = assert!(::a() == 2); + | ^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs index 6d6d793c62b76..4089ec7288526 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs @@ -14,3 +14,4 @@ pub const fn foobar() -> u32 { } const VAR: u32 = foobar(); +//~^ ERROR: `foobar` is not yet stable as a const fn diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr index 232de41c769e2..918d6ebf99226 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr @@ -4,5 +4,13 @@ error: feature `const_bar` implying `const_foobar` does not exist LL | #[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: `foobar` is not yet stable as a const fn + --> $DIR/const-stability-attribute-implies-missing.rs:16:18 + | +LL | const VAR: u32 = foobar(); + | ^^^^^^^^ + | + = help: add `#![feature(const_foobar)]` to the crate attributes to enable + +error: aborting due to 2 previous errors diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs index b7e49873da81a..20231dc83db91 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs @@ -1,7 +1,10 @@ +// ignore-macos: cycle error does not appear on apple + use std::sync::Mutex; enum Foo { X(Mutex>) } //~^ ERROR recursive type `Foo` has infinite size +//~| ERROR cycle detected impl Foo { fn bar(self) {} } diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr index e34eb04bc04fa..22f8519d0ef84 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr @@ -1,5 +1,5 @@ error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-6.rs:3:1 + --> $DIR/issue-17431-6.rs:5:1 | LL | enum Foo { X(Mutex>) } | ^^^^^^^^ --- recursive without indirection @@ -9,6 +9,17 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum Foo { X(Mutex>>) } | ++++ + -error: aborting due to 1 previous error +error[E0391]: cycle detected when computing when `Foo` needs drop + --> $DIR/issue-17431-6.rs:5:1 + | +LL | enum Foo { X(Mutex>) } + | ^^^^^^^^ + | + = note: ...which immediately requires computing when `Foo` needs drop again + = note: cycle used when computing whether `Foo` needs drop + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/suggestions/derive-trait-for-method-call.rs b/tests/ui/suggestions/derive-trait-for-method-call.rs index 25043da52aa01..b5ce0078c9bc8 100644 --- a/tests/ui/suggestions/derive-trait-for-method-call.rs +++ b/tests/ui/suggestions/derive-trait-for-method-call.rs @@ -19,7 +19,7 @@ struct CloneStruct { struct Foo (X, Y); impl Foo { fn test(&self) -> (X, Y) { - (self.0, self.1) + (self.0.clone(), self.1.clone()) } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs index 255cab06070c6..c24672816acdb 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -64,6 +64,8 @@ mod bay { fn use_it<'a>(val: Box + 'a>) -> &'a () { val.use_self() + //~^ ERROR: cannot return value referencing function parameter `val` + //~| ERROR: borrowed data escapes outside of function } } @@ -86,6 +88,7 @@ mod bax { fn use_it<'a>(val: Box + 'a>) -> &'a () { val.use_self() + //~^ ERROR: cannot return value referencing function parameter `val` } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr index a7e03f491b9e6..505765d2b41f6 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -17,7 +17,7 @@ LL | val.use_self() | `val` is borrowed here error[E0515]: cannot return value referencing function parameter `val` - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:112:9 | LL | val.use_self() | ---^^^^^^^^^^^ @@ -25,6 +25,50 @@ LL | val.use_self() | returns a value referencing data owned by the current function | `val` is borrowed here -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 + | +LL | fn use_it<'a>(val: Box + 'a>) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30 + | +LL | impl MyTrait for Box> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box + '_> { + | ++++ + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:90:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0515`. +Some errors have detailed explanations: E0515, E0521. +For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index ae3cd315c83ec..574aea9cc6e63 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -36,6 +36,7 @@ mod bar { fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { val.use_self() + //~^ ERROR: borrowed data escapes } } @@ -53,6 +54,7 @@ mod baz { fn use_it<'a>(val: &'a Box) -> &'a () { val.use_self() + //~^ ERROR: borrowed data escapes } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index da72c8ebf19b6..6effaf61099ec 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -24,7 +24,7 @@ LL | impl MyTrait for dyn ObjectTrait + '_ { | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:70:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:72:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | -- --- `val` is a reference that is only valid in the function body @@ -37,7 +37,7 @@ LL | val.use_self() | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:65:14 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:14 | LL | impl dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement @@ -49,7 +49,7 @@ LL | impl dyn ObjectTrait + '_ { | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:90:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:92:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | -- --- `val` is a reference that is only valid in the function body @@ -62,7 +62,7 @@ LL | val.use_self() | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:26 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:26 | LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement @@ -75,7 +75,7 @@ LL | impl MyTrait for dyn ObjectTrait + '_ {} | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:110:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:112:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | -- --- `val` is a reference that is only valid in the function body @@ -88,7 +88,7 @@ LL | MyTrait::use_self(val) | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:106:26 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:26 | LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement @@ -100,6 +100,56 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for dyn ObjectTrait + '_ {} | ++++ -error: aborting due to 4 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:38:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:26 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:56:9 + | +LL | fn use_it<'a>(val: &'a Box) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:50:30 + | +LL | impl MyTrait for Box { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box { + | ++++ + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.rs b/tests/ui/suggestions/impl-trait-missing-lifetime.rs index 6f7c912d707cf..b03d61614936f 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime.rs +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.rs @@ -8,6 +8,7 @@ fn f(_: impl Iterator) {} // But that lifetime does not participate in resolution. fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } //~^ ERROR missing lifetime specifier +//~| ERROR lifetime may not live long enough // This is understood as `fn foo<'_1>(_: impl Iterator) {}`. async fn h(_: impl Iterator) {} diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr index c1dbaae0649a0..70998b67c04bf 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -20,7 +20,7 @@ LL + fn g(mut x: impl Iterator) -> Option<()> { x.next() } | error[E0106]: missing lifetime specifier - --> $DIR/impl-trait-missing-lifetime.rs:16:60 + --> $DIR/impl-trait-missing-lifetime.rs:17:60 | LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ^^ expected named lifetime parameter @@ -41,13 +41,19 @@ LL + async fn i(mut x: impl Iterator) -> Option<()> { x.next() } | error: lifetime may not live long enough - --> $DIR/impl-trait-missing-lifetime.rs:16:69 + --> $DIR/impl-trait-missing-lifetime.rs:17:69 | LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ----------------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` | | | return type `impl Future>` contains a lifetime `'1` -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime.rs:9:63 + | +LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ----- has type `x` ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/issue-102892.rs b/tests/ui/suggestions/issue-102892.rs index c1a791d8d857a..ac7f16f8c65b1 100644 --- a/tests/ui/suggestions/issue-102892.rs +++ b/tests/ui/suggestions/issue-102892.rs @@ -9,6 +9,7 @@ struct B; fn process_without_annot(arc: &Arc<(A, B)>) { let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! + //~^ ERROR: cannot move out of an `Arc` } fn process_with_annot(arc: &Arc<(A, B)>) { diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr index e64a89ffe3308..38f19b3321887 100644 --- a/tests/ui/suggestions/issue-102892.stderr +++ b/tests/ui/suggestions/issue-102892.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-102892.rs:15:26 + --> $DIR/issue-102892.rs:16:26 | LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too | ------ ^^^^^^ expected `(A, B)`, found `&(A, B)` @@ -19,7 +19,7 @@ LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too | + error[E0308]: mismatched types - --> $DIR/issue-102892.rs:20:32 + --> $DIR/issue-102892.rs:21:32 | LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | ^^^^^^^^^^^^^^ expected `(A, B)`, found `&mut (A, B)` @@ -37,7 +37,7 @@ LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggest | ++++ error[E0308]: mismatched types - --> $DIR/issue-102892.rs:20:48 + --> $DIR/issue-102892.rs:21:48 | LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | ^^^^^^^^^^ expected `A`, found `&A` @@ -52,6 +52,23 @@ help: alternatively, consider changing the type annotation LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | + -error: aborting due to 3 previous errors +error[E0507]: cannot move out of an `Arc` + --> $DIR/issue-102892.rs:11:18 + | +LL | let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! + | - - ^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the dereference here + | +LL - let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! +LL + let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed! + | + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0507. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-86667.rs b/tests/ui/suggestions/issue-86667.rs index 366787df1b4dd..b1a7e6e966517 100644 --- a/tests/ui/suggestions/issue-86667.rs +++ b/tests/ui/suggestions/issue-86667.rs @@ -4,14 +4,15 @@ // compile-flags: --edition 2018 async fn a(s1: &str, s2: &str) -> &str { -//~^ ERROR: missing lifetime specifier [E0106] + //~^ ERROR: missing lifetime specifier [E0106] s1 -//~^ ERROR: lifetime may not live long enough + //~^ ERROR: lifetime may not live long enough } fn b(s1: &str, s2: &str) -> &str { -//~^ ERROR: missing lifetime specifier [E0106] + //~^ ERROR: missing lifetime specifier [E0106] s1 + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/suggestions/issue-86667.stderr b/tests/ui/suggestions/issue-86667.stderr index 8d611641626e1..e3d673ff23318 100644 --- a/tests/ui/suggestions/issue-86667.stderr +++ b/tests/ui/suggestions/issue-86667.stderr @@ -31,6 +31,15 @@ LL | LL | s1 | ^^ returning this value requires that `'1` must outlive `'static` -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/issue-86667.rs:14:5 + | +LL | fn b(s1: &str, s2: &str) -> &str { + | - let's call the lifetime of this reference `'1` +LL | +LL | s1 + | ^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs index 01dcc94f7476e..85dd6a5635a21 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.rs +++ b/tests/ui/suggestions/missing-lifetime-specifier.rs @@ -1,4 +1,6 @@ // different number of duplicated diagnostics on different targets +// only-x86_64 +// only-linux // compile-flags: -Zdeduplicate-diagnostics=yes #![allow(bare_trait_objects)] @@ -18,21 +20,31 @@ pub union Qux<'t, 'k, I> { trait Tar<'t, 'k, I> {} thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static a: RefCell>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static b: RefCell>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static c: RefCell>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static d: RefCell>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr index 7a7ef47c35b70..62eca16214871 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:21:44 + --> $DIR/missing-lifetime-specifier.rs:25:44 | LL | static a: RefCell>>> = RefCell::new(HashMap::new()); | ^^^ expected 2 lifetime parameters @@ -11,9 +11,11 @@ LL | static a: RefCell>>>> = RefC | ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:21:44 + --> $DIR/missing-lifetime-specifier.rs:25:44 | LL | / thread_local! { +LL | | +LL | | LL | | static a: RefCell>>> = RefCell::new(HashMap::new()); | | ^^^ expected 2 lifetime parameters LL | | @@ -24,7 +26,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:26:44 + --> $DIR/missing-lifetime-specifier.rs:33:44 | LL | static b: RefCell>>> = RefCell::new(HashMap::new()); | ^^^^ expected 2 lifetime parameters @@ -38,9 +40,12 @@ LL | static b: RefCell>> | +++++++ ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:26:44 + --> $DIR/missing-lifetime-specifier.rs:33:44 | LL | / thread_local! { +LL | | +LL | | +LL | | LL | | static b: RefCell>>> = RefCell::new(HashMap::new()); | | ^^^^ expected 2 lifetime parameters | | | @@ -53,7 +58,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:31:47 + --> $DIR/missing-lifetime-specifier.rs:40:47 | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -65,9 +70,11 @@ LL | static c: RefCell>>>> = | +++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:31:47 + --> $DIR/missing-lifetime-specifier.rs:40:47 | LL | / thread_local! { +LL | | +LL | | LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); | | ^ expected 2 lifetime parameters LL | | @@ -78,7 +85,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:36:44 + --> $DIR/missing-lifetime-specifier.rs:48:44 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ ^ expected 2 lifetime parameters @@ -92,9 +99,12 @@ LL | static d: RefCell $DIR/missing-lifetime-specifier.rs:36:44 + --> $DIR/missing-lifetime-specifier.rs:48:44 | LL | / thread_local! { +LL | | +LL | | +LL | | LL | | static d: RefCell>>>> = RefCell::new(HashMap::new()); | | ^ ^ expected 2 lifetime parameters | | | @@ -107,7 +117,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:46:44 + --> $DIR/missing-lifetime-specifier.rs:58:44 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -119,7 +129,7 @@ LL | static f: RefCell>>>> = | +++++++ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:46:44 + --> $DIR/missing-lifetime-specifier.rs:58:44 | LL | / thread_local! { LL | | static f: RefCell>>>> = RefCell::new(HashMap::new()); @@ -133,7 +143,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:42:44 + --> $DIR/missing-lifetime-specifier.rs:54:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -141,7 +151,7 @@ LL | static e: RefCell>>>> = RefCell: | expected 2 lifetime arguments | note: union defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:14:11 + --> $DIR/missing-lifetime-specifier.rs:16:11 | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- @@ -151,7 +161,7 @@ LL | static e: RefCell>>>> = | +++++++++ error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:46:45 + --> $DIR/missing-lifetime-specifier.rs:58:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -159,7 +169,7 @@ LL | static f: RefCell>>>> = RefCell | expected 2 lifetime arguments | note: trait defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:18:7 + --> $DIR/missing-lifetime-specifier.rs:20:7 | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- @@ -168,7 +178,199 @@ help: add missing lifetime argument LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++++ -error: aborting due to 12 previous errors +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:22:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static a: RefCell>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:22:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static a: RefCell>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +LL | | static b: RefCell>>> = RefCell::new(HashMap::new()); + | | - let's call the lifetime of this reference `'1` +LL | | +LL | | +LL | | } + | |_^ returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'3` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:37:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:37:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +LL | | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | | - let's call the lifetime of this reference `'1` +LL | | +LL | | +LL | | } + | |_^ returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'3` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: aborting due to 22 previous errors Some errors have detailed explanations: E0106, E0107. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.rs b/tests/ui/suggestions/missing-lt-for-hrtb.rs index 04ea3d831c93a..a48c5665d67a4 100644 --- a/tests/ui/suggestions/missing-lt-for-hrtb.rs +++ b/tests/ui/suggestions/missing-lt-for-hrtb.rs @@ -8,6 +8,8 @@ fn main() { let x = S(&|x| { println!("hi"); x + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough }); x.0(&X(&())); } diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.stderr b/tests/ui/suggestions/missing-lt-for-hrtb.stderr index fa515644431ac..e8c536ac47d50 100644 --- a/tests/ui/suggestions/missing-lt-for-hrtb.stderr +++ b/tests/ui/suggestions/missing-lt-for-hrtb.stderr @@ -31,6 +31,28 @@ help: consider using one of the available lifetimes here LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X<'lifetime>); | +++++++++ +++++++++++ -error: aborting due to 2 previous errors +error: lifetime may not live long enough + --> $DIR/missing-lt-for-hrtb.rs:10:9 + | +LL | let x = S(&|x| { + | -- return type of closure is &'2 X<'_> + | | + | has type `&'1 X<'_>` +LL | println!("hi"); +LL | x + | ^ returning this value requires that `'1` must outlive `'2` + +error: lifetime may not live long enough + --> $DIR/missing-lt-for-hrtb.rs:10:9 + | +LL | let x = S(&|x| { + | -- return type of closure is &X<'4> + | | + | has type `&X<'3>` +LL | println!("hi"); +LL | x + | ^ returning this value requires that `'3` must outlive `'4` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/traits/self-without-lifetime-constraint.rs b/tests/ui/traits/self-without-lifetime-constraint.rs index 99013d32ab8d0..50901173b763d 100644 --- a/tests/ui/traits/self-without-lifetime-constraint.rs +++ b/tests/ui/traits/self-without-lifetime-constraint.rs @@ -15,6 +15,7 @@ impl<'a> ValueRef<'a> { match *self { ValueRef::Text(t) => { std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x)) + //~^ ERROR: cannot return value referencing function parameter `x` } _ => Err(FromSqlError::InvalidType), } diff --git a/tests/ui/traits/self-without-lifetime-constraint.stderr b/tests/ui/traits/self-without-lifetime-constraint.stderr index 0a5ae8a027e48..8997d2a98b323 100644 --- a/tests/ui/traits/self-without-lifetime-constraint.stderr +++ b/tests/ui/traits/self-without-lifetime-constraint.stderr @@ -1,5 +1,5 @@ error: `impl` item signature doesn't match `trait` item signature - --> $DIR/self-without-lifetime-constraint.rs:45:5 + --> $DIR/self-without-lifetime-constraint.rs:46:5 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` @@ -10,10 +10,20 @@ LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - --> $DIR/self-without-lifetime-constraint.rs:41:60 + --> $DIR/self-without-lifetime-constraint.rs:42:60 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; | ^^^^ consider borrowing this type parameter in the trait -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing function parameter `x` + --> $DIR/self-without-lifetime-constraint.rs:17:87 + | +LL | std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x)) + | ^^^^--^ + | | | + | | `x` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs index ac32dbde04b1c..1a5daa13458c6 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -6,6 +6,7 @@ mod test_type_param_static { fn defining(s: A) -> Ty { s } fn assert_static() {} fn test() where Ty: 'static { assert_static::() } + //~^ ERROR: the parameter type `A` may not live long enough } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index ff11aee40261b..d1c06330c15e0 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -12,6 +12,20 @@ help: consider adding an explicit lifetime bound LL | type Ty = impl Sized + 'static; | +++++++++ -error: aborting due to 1 previous error +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check4_static.rs:8:41 + | +LL | fn test() where Ty: 'static { assert_static::() } + | ^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn test() where Ty: 'static { assert_static::() } + | +++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs index 3d6c826d6ac5a..2d9345a3e5e8e 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.rs +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -7,6 +7,7 @@ type Pointer = impl std::ops::Deref; fn test() -> Pointer<_> { //~^ ERROR: the placeholder `_` is not allowed within types Box::new(1) + //~^ ERROR: expected generic type parameter, found `i32` } fn main() { diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index c5cacfd3cd351..ebd78e5b7a54f 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -8,7 +8,7 @@ LL | fn test() -> Pointer<_> { | help: replace with the correct return type: `Pointer` error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/issue-77179.rs:17:25 + --> $DIR/issue-77179.rs:18:25 | LL | fn bar() -> Pointer<_>; | ^ @@ -16,6 +16,16 @@ LL | fn bar() -> Pointer<_>; | not allowed in type signatures | help: use type parameters instead: `T` -error: aborting due to 2 previous errors +error[E0792]: expected generic type parameter, found `i32` + --> $DIR/issue-77179.rs:9:5 + | +LL | type Pointer = impl std::ops::Deref; + | - this generic parameter must be used with a generic type parameter +... +LL | Box::new(1) + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0121, E0792. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs index 0f0a02e97d82d..6431cf37df7ab 100644 --- a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs +++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -14,5 +14,7 @@ mod foo { } fn main() { - let _: foo::Foo = std::mem::transmute(0u8); + unsafe { + let _: foo::Foo = std::mem::transmute(0u8); + } } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs index ea73b8b3c4a28..8537eb7177484 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs @@ -33,6 +33,7 @@ fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { //~^ ERROR trait takes 1 lifetime argument but 0 lifetime arguments were supplied // Here, the omitted lifetimes are expanded to distinct things. same_type(x, y) + //~^ ERROR borrowed data escapes outside of function } fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr index d73aef851fd76..6e6c649ca3d57 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr @@ -34,6 +34,22 @@ note: trait defined here, with 1 lifetime parameter: `'a` LL | trait Foo<'a,T> { | ^^^ -- -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/unboxed-closure-sugar-region.rs:35:5 + | +LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { + | - - `y` declared here, outside of the function body + | | + | `x` is a reference that is only valid in the function body + | has type `&dyn Foo<'1, (isize,), Output = ()>` +... +LL | same_type(x, y) + | ^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0521. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs b/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs index 3d049cc5639c0..ebc3879854434 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs @@ -14,6 +14,7 @@ fn meh() -> Box Meh<'_>> //~ ERROR cannot be used here } fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime specifier +//~^ ERROR lifetime may not live long enough fn main() { let x = 5; diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr index cd74d27dcb55f..5d2954d1d71e0 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -45,7 +45,15 @@ help: consider introducing a named lifetime parameter LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y } | ++++ ~~ ~~ ~~ -error: aborting due to 5 previous errors +error: lifetime may not live long enough + --> $DIR/underscore-lifetime-binders.rs:16:43 + | +LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } + | - ^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0106, E0637. For more information about an error, try `rustc --explain E0106`. From 795be51dd931848b8cbf3dc84c526ca92634803c Mon Sep 17 00:00:00 2001 From: Amanda Stjerna Date: Wed, 7 Feb 2024 14:51:51 +0100 Subject: [PATCH 648/676] Make `RegionName` `Copy` by (transitively) interning the few string variants --- .../src/diagnostics/region_name.rs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index c9de36e9064e2..a31e6ce5f297f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -15,7 +15,7 @@ use crate::{universal_regions::DefiningTy, MirBorrowckCtxt}; /// A name for a particular region used in emitting diagnostics. This name could be a generated /// name like `'1`, a name used by the user like `'a`, or a name like `'static`. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) struct RegionName { /// The name of the region (interned). pub(crate) name: Symbol, @@ -26,7 +26,7 @@ pub(crate) struct RegionName { /// Denotes the source of a region that is named by a `RegionName`. For example, a free region that /// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get `Static`. /// This helps to print the right kinds of diagnostics. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) enum RegionNameSource { /// A bound (not free) region that was instantiated at the def site (not an HRTB). NamedEarlyParamRegion(Span), @@ -43,7 +43,7 @@ pub(crate) enum RegionNameSource { /// The region corresponding to the return type of a closure. AnonRegionFromOutput(RegionNameHighlight, &'static str), /// The region from a type yielded by a coroutine. - AnonRegionFromYieldTy(Span, String), + AnonRegionFromYieldTy(Span, Symbol), /// An anonymous region from an async fn. AnonRegionFromAsyncFn(Span), /// An anonymous region from an impl self type or trait @@ -52,7 +52,7 @@ pub(crate) enum RegionNameSource { /// Describes what to highlight to explain to the user that we're giving an anonymous region a /// synthesized name, and how to highlight it. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) enum RegionNameHighlight { /// The anonymous region corresponds to a reference that was found by traversing the type in the HIR. MatchedHirTy(Span), @@ -60,11 +60,11 @@ pub(crate) enum RegionNameHighlight { MatchedAdtAndSegment(Span), /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference. - CannotMatchHirTy(Span, String), + CannotMatchHirTy(Span, Symbol), /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, and *even if* we print out the full name of the type, the region name won't /// be included. This currently occurs for opaque types like `impl Future`. - Occluded(Span, String), + Occluded(Span, Symbol), } impl RegionName { @@ -249,7 +249,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { assert!(self.regioncx.universal_regions().is_universal_region(fr)); match self.region_names.borrow_mut().entry(fr) { - IndexEntry::Occupied(precomputed_name) => Some(precomputed_name.get().clone()), + IndexEntry::Occupied(precomputed_name) => Some(*precomputed_name.get()), IndexEntry::Vacant(slot) => { let new_name = self .give_name_from_error_region(fr) @@ -262,8 +262,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr) }); - if let Some(new_name) = &new_name { - slot.insert(new_name.clone()); + if let Some(new_name) = new_name { + slot.insert(new_name); } debug!("give_region_a_name: gave name {:?}", new_name); @@ -460,9 +460,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ); if type_name.contains(&format!("'{counter}")) { // Only add a label if we can confirm that a region was labelled. - RegionNameHighlight::CannotMatchHirTy(span, type_name) + RegionNameHighlight::CannotMatchHirTy(span, Symbol::intern(&type_name)) } else { - RegionNameHighlight::Occluded(span, type_name) + RegionNameHighlight::Occluded(span, Symbol::intern(&type_name)) } } @@ -882,7 +882,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Some(RegionName { name: self.synthesize_region_name(), - source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name), + source: RegionNameSource::AnonRegionFromYieldTy(yield_span, Symbol::intern(&type_name)), }) } @@ -974,7 +974,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Some(RegionName { name: region_name, source: RegionNameSource::AnonRegionFromArgument( - RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()), + RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?), ), }) } else { From 0ce71f6985cd9e798ed43456ed7dba437936a904 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 8 Feb 2024 11:06:51 +0200 Subject: [PATCH 649/676] make future diffs minimal --- src/bootstrap/src/core/builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 4bb8ed2fa67fb..83485abfa5618 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -732,7 +732,7 @@ impl<'a> Builder<'a> { check::Rls, check::Rustfmt, check::RustAnalyzer, - check::Bootstrap + check::Bootstrap, ), Kind::Test => describe!( crate::core::build_steps::toolstate::ToolStateCheck, @@ -866,7 +866,7 @@ impl<'a> Builder<'a> { install::Miri, install::LlvmTools, install::Src, - install::Rustc + install::Rustc, ), Kind::Run => describe!( run::ExpandYamlAnchors, From f676c3d504c14c507f8084500f7da1dcfd810aa6 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 8 Feb 2024 11:06:02 +0100 Subject: [PATCH 650/676] Remove myself from review rotation. --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index eba8e283815c8..ef3f3693e6174 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -669,7 +669,6 @@ libs = [ "@cuviper", "@joshtriplett", "@Mark-Simulacrum", - "@m-ou-se", ] bootstrap = [ "@Mark-Simulacrum", From 30793ca8181c4633a29784281b99c56c87a6fe16 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 7 Feb 2024 16:23:39 +0100 Subject: [PATCH 651/676] Match `min_exhaustive_patterns` implementation with `exhaustive_patterns` --- compiler/rustc_mir_build/src/build/matches/simplify.rs | 3 ++- compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 065c93e86a866..14b7fb9ce6fff 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -271,7 +271,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { i == variant_index || { - self.tcx.features().exhaustive_patterns + (self.tcx.features().exhaustive_patterns + || self.tcx.features().min_exhaustive_patterns) && !v .inhabited_predicate(self.tcx, adt_def) .instantiate(self.tcx, args) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 1156e8be13e74..692f4511bb807 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -665,7 +665,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // Emit an extra note if the first uncovered witness would be uninhabited // if we disregard visibility. - let witness_1_is_privately_uninhabited = if self.tcx.features().exhaustive_patterns + let witness_1_is_privately_uninhabited = if (self.tcx.features().exhaustive_patterns + || self.tcx.features().min_exhaustive_patterns) && let Some(witness_1) = witnesses.get(0) && let ty::Adt(adt, args) = witness_1.ty().kind() && adt.is_enum() From 4733b1bba50c06bec217c1f3c28343d7a2043146 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 8 Feb 2024 11:27:46 +0100 Subject: [PATCH 652/676] Test `min_exhaustive_patterns` in more cases --- ...ultivariant.min_exhaustive_patterns.stderr | 11 +++++ .../run_pass/multivariant.rs | 5 +- ...ited-union-ref.exhaustive_patterns.stderr} | 6 +-- ...d-union-ref.min_exhaustive_patterns.stderr | 46 +++++++++++++++++++ .../usefulness/always-inhabited-union-ref.rs | 7 ++- ...rivately-empty.exhaustive_patterns.stderr} | 4 +- ...ately-empty.min_exhaustive_patterns.stderr | 30 ++++++++++++ .../usefulness/match-privately-empty.rs | 12 ++--- ...slice_of_empty.exhaustive_patterns.stderr} | 2 +- ...ce_of_empty.min_exhaustive_patterns.stderr | 38 +++++++++++++++ tests/ui/pattern/usefulness/slice_of_empty.rs | 9 +++- .../ui/rfcs/rfc-0000-never_patterns/typeck.rs | 4 +- .../rfc-0000-never_patterns/unreachable.rs | 2 +- ...ed-irrefutable.exhaustive_patterns.stderr} | 4 +- ...irrefutable.min_exhaustive_patterns.stderr | 26 +++++++++++ .../ui/uninhabited/uninhabited-irrefutable.rs | 5 +- 16 files changed, 188 insertions(+), 23 deletions(-) create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr rename tests/ui/pattern/usefulness/{always-inhabited-union-ref.stderr => always-inhabited-union-ref.exhaustive_patterns.stderr} (87%) create mode 100644 tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr rename tests/ui/pattern/usefulness/{match-privately-empty.stderr => match-privately-empty.exhaustive_patterns.stderr} (87%) create mode 100644 tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr rename tests/ui/pattern/usefulness/{slice_of_empty.stderr => slice_of_empty.exhaustive_patterns.stderr} (93%) create mode 100644 tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr rename tests/ui/uninhabited/{uninhabited-irrefutable.stderr => uninhabited-irrefutable.exhaustive_patterns.stderr} (91%) create mode 100644 tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..b54341f82c794 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr @@ -0,0 +1,11 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/multivariant.rs:7:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs index 72652ef60349a..bc2386e5d23d8 100644 --- a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs @@ -1,8 +1,11 @@ // Test precise capture of a multi-variant enum (when remaining variants are // visibly uninhabited). +// revisions: min_exhaustive_patterns exhaustive_patterns // edition:2021 // run-pass -#![feature(exhaustive_patterns)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] pub fn main() { diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr similarity index 87% rename from tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr rename to tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr index cd5c283f9fd93..553daff2d969d 100644 --- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/always-inhabited-union-ref.rs:23:11 + --> $DIR/always-inhabited-union-ref.rs:26:11 | LL | match uninhab_ref() { | ^^^^^^^^^^^^^ @@ -14,13 +14,13 @@ LL + } | error[E0004]: non-exhaustive patterns: type `Foo` is non-empty - --> $DIR/always-inhabited-union-ref.rs:27:11 + --> $DIR/always-inhabited-union-ref.rs:30:11 | LL | match uninhab_union() { | ^^^^^^^^^^^^^^^ | note: `Foo` defined here - --> $DIR/always-inhabited-union-ref.rs:10:11 + --> $DIR/always-inhabited-union-ref.rs:13:11 | LL | pub union Foo { | ^^^ diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..a1d8002c64895 --- /dev/null +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr @@ -0,0 +1,46 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/always-inhabited-union-ref.rs:7:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: type `&!` is non-empty + --> $DIR/always-inhabited-union-ref.rs:26:11 + | +LL | match uninhab_ref() { + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_ref() { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `Foo` is non-empty + --> $DIR/always-inhabited-union-ref.rs:30:11 + | +LL | match uninhab_union() { + | ^^^^^^^^^^^^^^^ + | +note: `Foo` defined here + --> $DIR/always-inhabited-union-ref.rs:13:11 + | +LL | pub union Foo { + | ^^^ + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_union() { +LL + _ => todo!(), +LL + } + | + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs index 7d1cac8a442f5..247b7f21f6866 100644 --- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -1,9 +1,12 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns + // The precise semantics of inhabitedness with respect to unions and references is currently // undecided. This test file currently checks a conservative choice. -#![feature(exhaustive_patterns)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] - #![allow(dead_code)] #![allow(unreachable_code)] diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr similarity index 87% rename from tests/ui/pattern/usefulness/match-privately-empty.stderr rename to tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr index d760790dff6fe..708a1511244c2 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.stderr +++ b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered - --> $DIR/match-privately-empty.rs:13:11 + --> $DIR/match-privately-empty.rs:16:11 | LL | match private::DATA { | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered @@ -12,7 +12,7 @@ note: `Option` defined here = note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ }) => {}, +LL ~ Some(private::Private { misc: false, .. }) => {}, LL + Some(Private { misc: true, .. }) => todo!() | diff --git a/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..a6ce02c0c3c6a --- /dev/null +++ b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr @@ -0,0 +1,30 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/match-privately-empty.rs:3:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + --> $DIR/match-privately-empty.rs:16:11 + | +LL | match private::DATA { + | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Some(private::Private { misc: false, .. }) => {}, +LL + Some(Private { misc: true, .. }) => todo!() + | + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-privately-empty.rs b/tests/ui/pattern/usefulness/match-privately-empty.rs index 315eb03d16564..67a9aa2e91614 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.rs +++ b/tests/ui/pattern/usefulness/match-privately-empty.rs @@ -1,5 +1,8 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] -#![feature(exhaustive_patterns)] mod private { pub struct Private { @@ -11,11 +14,8 @@ mod private { fn main() { match private::DATA { - //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered None => {} - Some(private::Private { - misc: false, - .. - }) => {} + Some(private::Private { misc: false, .. }) => {} } } diff --git a/tests/ui/pattern/usefulness/slice_of_empty.stderr b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr similarity index 93% rename from tests/ui/pattern/usefulness/slice_of_empty.stderr rename to tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr index d56360d4cec07..9770f680b2da8 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.stderr +++ b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/slice_of_empty.rs:18:11 + --> $DIR/slice_of_empty.rs:22:11 | LL | match nevers { | ^^^^^^ pattern `&[]` not covered diff --git a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..3b9e71f50d5ff --- /dev/null +++ b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr @@ -0,0 +1,38 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/slice_of_empty.rs:3:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/slice_of_empty.rs:11:11 + | +LL | match nevers { + | ^^^^^^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &[] => (), +LL ~ &[_, ..] => todo!(), + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice_of_empty.rs:22:11 + | +LL | match nevers { + | ^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[_] => (), +LL ~ &[] | &[_, _, ..] => todo!(), + | + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/slice_of_empty.rs b/tests/ui/pattern/usefulness/slice_of_empty.rs index 3cbd0eba57fd1..5f64dd3fecc9a 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.rs +++ b/tests/ui/pattern/usefulness/slice_of_empty.rs @@ -1,11 +1,15 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] -#![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] fn main() {} fn foo(nevers: &[!]) { match nevers { + //[min_exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[_, ..]` not covered &[] => (), }; @@ -16,7 +20,8 @@ fn foo(nevers: &[!]) { }; match nevers { - //~^ ERROR non-exhaustive patterns: `&[]` not covered + //[exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[]` not covered + //[min_exhaustive_patterns]~^^ ERROR non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered &[_] => (), }; } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs index 31a23fa002c30..72ee4d24bb629 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -2,7 +2,7 @@ //[pass] check-pass //[fail] check-fail #![feature(never_patterns)] -#![feature(exhaustive_patterns)] +#![feature(min_exhaustive_patterns)] #![allow(incomplete_features)] #[derive(Copy, Clone)] @@ -107,7 +107,7 @@ fn never_pattern_typeck_pass(void: Void) { } match (&[] as &[Void]) { [] => {} - [!], + [!, ..], } // Accept on a composite empty type. match None::<&(u32, Void)> { diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs index df8e22abf6232..0374cbdbc1fd2 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs @@ -2,7 +2,7 @@ //[normal] check-pass #![feature(never_patterns)] #![allow(incomplete_features)] -#![cfg_attr(exh_pats, feature(exhaustive_patterns))] +#![cfg_attr(exh_pats, feature(min_exhaustive_patterns))] #![allow(dead_code, unreachable_code)] #![deny(unreachable_patterns)] diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr similarity index 91% rename from tests/ui/uninhabited/uninhabited-irrefutable.stderr rename to tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr index 304e738ed2561..c9131a8372ab1 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0005]: refutable pattern in local binding - --> $DIR/uninhabited-irrefutable.rs:29:9 + --> $DIR/uninhabited-irrefutable.rs:32:9 | LL | let Foo::D(_y, _z) = x; | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered @@ -7,7 +7,7 @@ LL | let Foo::D(_y, _z) = x; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `Foo` defined here - --> $DIR/uninhabited-irrefutable.rs:18:6 + --> $DIR/uninhabited-irrefutable.rs:21:6 | LL | enum Foo { | ^^^ diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..c9131a8372ab1 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr @@ -0,0 +1,26 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/uninhabited-irrefutable.rs:32:9 + | +LL | let Foo::D(_y, _z) = x; + | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Foo` defined here + --> $DIR/uninhabited-irrefutable.rs:21:6 + | +LL | enum Foo { + | ^^^ +LL | +LL | A(foo::SecretlyEmpty), + | - not covered + = note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future + = note: the matched value is of type `Foo` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Foo::D(_y, _z) = x else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs index cfd60a8d903fa..2ef3b668cb089 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.rs +++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs @@ -1,5 +1,8 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, allow(incomplete_features))] #![feature(never_type)] -#![feature(exhaustive_patterns)] mod foo { pub struct SecretlyEmpty { From d80d7ea1e325ded1b8b57204cbf98e65b6e0957c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 8 Feb 2024 12:28:35 +0000 Subject: [PATCH 653/676] Add some tests for associated type normalization edge cases --- tests/ui/privacy/projections.rs | 60 +++++++++++++++++++++++++++ tests/ui/privacy/projections.stderr | 62 ++++++++++++++++++++++++++++ tests/ui/privacy/projections2.rs | 38 +++++++++++++++++ tests/ui/privacy/projections2.stderr | 34 +++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 tests/ui/privacy/projections.rs create mode 100644 tests/ui/privacy/projections.stderr create mode 100644 tests/ui/privacy/projections2.rs create mode 100644 tests/ui/privacy/projections2.stderr diff --git a/tests/ui/privacy/projections.rs b/tests/ui/privacy/projections.rs new file mode 100644 index 0000000000000..0e6590de4f5b4 --- /dev/null +++ b/tests/ui/privacy/projections.rs @@ -0,0 +1,60 @@ +mod m { + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` +} + +trait Trait { + type A; +} + +impl Trait for u8 { + type A = u8; +} + +fn check() -> ::A { + //~^ ERROR: `Priv` is private + 0 +} + +trait Trait2 { + type A; +} + +impl Trait2 for u8 { + type A = m::Leak; + //~^ ERROR: `Priv` is private + //~| ERROR: private type `Priv` in public interface +} + +fn check2() -> ::A { + //~^ ERROR: `Priv` is private + todo!() +} + +trait Trait3 { + type A; +} + +impl Trait3 for u8 { + type A = T::A; + //~^ ERROR: `Priv` is private + //~| ERROR: private type `Priv` in public interface +} + +fn check3() -> ::A { + todo!() +} + +trait Trait4 { + type A; +} + +impl Trait4 for u8 { + type A = T::A; +} + +fn check4() -> ::A { + todo!() +} + +fn main() {} diff --git a/tests/ui/privacy/projections.stderr b/tests/ui/privacy/projections.stderr new file mode 100644 index 0000000000000..010d77998e344 --- /dev/null +++ b/tests/ui/privacy/projections.stderr @@ -0,0 +1,62 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/projections.rs:3:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/projections.rs:2:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error[E0446]: private type `Priv` in public interface + --> $DIR/projections.rs:24:5 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type A = m::Leak; + | ^^^^^^^^^ can't leak private type + +error[E0446]: private type `Priv` in public interface + --> $DIR/projections.rs:39:5 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type A = T::A; + | ^^^^^^^^^^^^^^^^ can't leak private type + +error: type `Priv` is private + --> $DIR/projections.rs:14:15 + | +LL | fn check() -> ::A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:29:39 + | +LL | fn check2() -> ::A { + | _______________________________________^ +LL | | +LL | | todo!() +LL | | } + | |_^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:24:17 + | +LL | type A = m::Leak; + | ^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:39:24 + | +LL | type A = T::A; + | ^^^^^^^^^^^^^ private type + +error: aborting due to 6 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/projections2.rs b/tests/ui/privacy/projections2.rs new file mode 100644 index 0000000000000..1afbf6d196e58 --- /dev/null +++ b/tests/ui/privacy/projections2.rs @@ -0,0 +1,38 @@ +mod m { + use super::*; + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` + + trait Trait3 { + type A; + } + + impl Trait3 for u8 { + type A = T::A; + } + + pub trait Trait4 { + type A; + } + + impl Trait4 for u8 { + type A = ::A; + //~^ ERROR: private associated type `Trait3::A` in public interface + //~| ERROR: private trait `Trait3` in public interface + } +} + +pub trait Trait { + type A; +} + +impl Trait for u8 { + type A = u8; +} +use m::*; + +fn check4() -> ::A { + todo!() +} + +fn main() {} diff --git a/tests/ui/privacy/projections2.stderr b/tests/ui/privacy/projections2.stderr new file mode 100644 index 0000000000000..6eae9643c5a8e --- /dev/null +++ b/tests/ui/privacy/projections2.stderr @@ -0,0 +1,34 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/projections2.rs:4:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/projections2.rs:3:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error[E0446]: private associated type `Trait3::A` in public interface + --> $DIR/projections2.rs:19:9 + | +LL | type A; + | ---------------- `Trait3::A` declared as private +... +LL | type A = ::A; + | ^^^^^^^^^^^^^^^^ can't leak private associated type + +error[E0446]: private trait `Trait3` in public interface + --> $DIR/projections2.rs:19:9 + | +LL | trait Trait3 { + | ------------ `Trait3` declared as private +... +LL | type A = ::A; + | ^^^^^^^^^^^^^^^^ can't leak private trait + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0446`. From da4ec6ffa73fff5435e43de70c082adf895e9a59 Mon Sep 17 00:00:00 2001 From: zetanumbers Date: Thu, 8 Feb 2024 15:42:41 +0300 Subject: [PATCH 654/676] Deduplicate `tcx.instance_mir(instance)` calls in `try_instance_mir` --- compiler/rustc_mir_transform/src/inline.rs | 25 +++++++++------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index e77553a03d672..be19bd8349ed4 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1027,21 +1027,16 @@ fn try_instance_mir<'tcx>( tcx: TyCtxt<'tcx>, instance: InstanceDef<'tcx>, ) -> Result<&'tcx Body<'tcx>, &'static str> { - match instance { - ty::InstanceDef::DropGlue(_, Some(ty)) => match ty.kind() { - ty::Adt(def, args) => { - let fields = def.all_fields(); - for field in fields { - let field_ty = field.ty(tcx, args); - if field_ty.has_param() && field_ty.has_projections() { - return Err("cannot build drop shim for polymorphic type"); - } - } - - Ok(tcx.instance_mir(instance)) + if let ty::InstanceDef::DropGlue(_, Some(ty)) = instance + && let ty::Adt(def, args) = ty.kind() + { + let fields = def.all_fields(); + for field in fields { + let field_ty = field.ty(tcx, args); + if field_ty.has_param() && field_ty.has_projections() { + return Err("cannot build drop shim for polymorphic type"); } - _ => Ok(tcx.instance_mir(instance)), - }, - _ => Ok(tcx.instance_mir(instance)), + } } + Ok(tcx.instance_mir(instance)) } From ac559af98fa2c24a0e73c15e6d9019912473e6d4 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 30 Jan 2024 01:27:06 +0000 Subject: [PATCH 655/676] introduce `enter_forall` --- compiler/rustc_infer/src/infer/mod.rs | 21 +- .../src/infer/relate/higher_ranked.rs | 42 ++-- compiler/rustc_infer/src/infer/relate/nll.rs | 28 ++- .../src/opaque_hidden_inferred_bound.rs | 181 ++++++++--------- compiler/rustc_middle/src/ty/sty.rs | 1 + .../src/solve/assembly/structural_traits.rs | 53 ++--- .../src/solve/eval_ctxt/mod.rs | 18 +- .../src/solve/eval_ctxt/select.rs | 184 +++++++++--------- .../src/solve/trait_goals.rs | 12 +- .../src/traits/coherence.rs | 2 +- .../src/traits/error_reporting/ambiguity.rs | 87 +++++---- .../error_reporting/on_unimplemented.rs | 53 ++--- .../src/traits/error_reporting/suggestions.rs | 146 +++++++------- .../error_reporting/type_err_ctxt_ext.rs | 132 +++++++------ compiler/rustc_type_ir/src/region_kind.rs | 2 +- 15 files changed, 520 insertions(+), 442 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2d8b47a9cc057..82690b9acbece 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1032,10 +1032,10 @@ impl<'tcx> InferCtxt<'tcx> { _ => {} } - let ty::SubtypePredicate { a_is_expected, a, b } = - self.instantiate_binder_with_placeholders(predicate); - - Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)) + // FIXME(tree_universes): leaking universes + self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { + Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)) + }) } pub fn region_outlives_predicate( @@ -1043,10 +1043,13 @@ impl<'tcx> InferCtxt<'tcx> { cause: &traits::ObligationCause<'tcx>, predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) { - let ty::OutlivesPredicate(r_a, r_b) = self.instantiate_binder_with_placeholders(predicate); - let origin = - SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); - self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + // FIXME(tree_universes): leaking universes + self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| { + let origin = SubregionOrigin::from_obligation_cause(cause, || { + RelateRegionParamBound(cause.span) + }); + self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + }) } /// Number of type variables created so far. @@ -1455,7 +1458,7 @@ impl<'tcx> InferCtxt<'tcx> { // Use this method if you'd like to find some substitution of the binder's // variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`] // that corresponds to your use case, consider whether or not you should - // use [`InferCtxt::instantiate_binder_with_placeholders`] instead. + // use [`InferCtxt::enter_forall`] instead. pub fn instantiate_binder_with_fresh_vars( &self, span: Span, diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 440df8c8936f9..cff544ed15400 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -38,24 +38,24 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. Note that this automatically creates // a new universe if needed. - let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup); + self.infcx.enter_forall(sup, |sup_prime| { + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other preexisting region variables -- can name + // the placeholders. + let sub_prime = + self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub); + debug!("a_prime={:?}", sub_prime); + debug!("b_prime={:?}", sup_prime); - // Next, we instantiate each bound region in the subtype - // with a fresh region variable. These region variables -- - // but no other preexisting region variables -- can name - // the placeholders. - let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub); - - debug!("a_prime={:?}", sub_prime); - debug!("b_prime={:?}", sup_prime); - - // Compare types now that bound regions have been replaced. - let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?; - - debug!("OK result={result:?}"); - // NOTE: returning the result here would be dangerous as it contains - // placeholders which **must not** be named afterwards. - Ok(()) + // Compare types now that bound regions have been replaced. + // FIXME(tree_universes): leaked dead universes + let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime); + if result.is_ok() { + debug!("OK result={result:?}"); + } + result.map(|_| ()) + }) } } @@ -106,6 +106,14 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(binder, delegate) } + pub fn enter_forall(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U + where + T: TypeFoldable> + Copy, + { + let value = self.instantiate_binder_with_placeholders(forall); + f(value) + } + /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that /// universe. diff --git a/compiler/rustc_infer/src/infer/relate/nll.rs b/compiler/rustc_infer/src/infer/relate/nll.rs index 8b80646a386c8..7e93ab995dbc6 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -309,6 +309,18 @@ where replaced } + fn enter_forall( + &mut self, + binder: ty::Binder<'tcx, T>, + f: impl FnOnce(&mut Self, T) -> U, + ) -> U + where + T: ty::TypeFoldable> + Copy, + { + let value = self.instantiate_binder_with_placeholders(binder); + f(self, value) + } + #[instrument(skip(self), level = "debug")] fn instantiate_binder_with_existentials(&mut self, binder: ty::Binder<'tcx, T>) -> T where @@ -630,10 +642,10 @@ where // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! - let b_replaced = self.instantiate_binder_with_placeholders(b); - let a_replaced = self.instantiate_binder_with_existentials(a); - - self.relate(a_replaced, b_replaced)?; + self.enter_forall(b, |this, b| { + let a = this.instantiate_binder_with_existentials(a); + this.relate(a, b) + })?; self.ambient_variance = variance; } @@ -650,10 +662,10 @@ where let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant); - let a_replaced = self.instantiate_binder_with_placeholders(a); - let b_replaced = self.instantiate_binder_with_existentials(b); - - self.relate(a_replaced, b_replaced)?; + self.enter_forall(a, |this, a| { + let b = this.instantiate_binder_with_existentials(b); + this.relate(a, b) + })?; self.ambient_variance = variance; } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index bed5d3c80c046..cf825be7a55ea 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -77,101 +77,104 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied() { - let predicate = infcx.instantiate_binder_with_placeholders(pred.kind()); - let ty::ClauseKind::Projection(proj) = predicate else { - continue; - }; - // Only check types, since those are the only things that may - // have opaques in them anyways. - let Some(proj_term) = proj.term.ty() else { continue }; + infcx.enter_forall(pred.kind(), |predicate| { + let ty::ClauseKind::Projection(proj) = predicate else { + return; + }; + // Only check types, since those are the only things that may + // have opaques in them anyways. + let Some(proj_term) = proj.term.ty() else { return }; - // HACK: `impl Trait` from an RPIT is "ok"... - if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() - && cx.tcx.parent(opaque_ty.def_id) == def_id - && matches!( - opaque.origin, - hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) - ) - { - continue; - } + // HACK: `impl Trait` from an RPIT is "ok"... + if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() + && cx.tcx.parent(opaque_ty.def_id) == def_id + && matches!( + opaque.origin, + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) + ) + { + return; + } - // HACK: `async fn() -> Self` in traits is "ok"... - // This is not really that great, but it's similar to why the `-> Self` - // return type is well-formed in traits even when `Self` isn't sized. - if let ty::Param(param_ty) = *proj_term.kind() - && param_ty.name == kw::SelfUpper - && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_)) - && opaque.in_trait - { - continue; - } + // HACK: `async fn() -> Self` in traits is "ok"... + // This is not really that great, but it's similar to why the `-> Self` + // return type is well-formed in traits even when `Self` isn't sized. + if let ty::Param(param_ty) = *proj_term.kind() + && param_ty.name == kw::SelfUpper + && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_)) + && opaque.in_trait + { + return; + } - let proj_ty = - Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args); - // For every instance of the projection type in the bounds, - // replace them with the term we're assigning to the associated - // type in our opaque type. - let proj_replacer = &mut BottomUpFolder { - tcx: cx.tcx, - ty_op: |ty| if ty == proj_ty { proj_term } else { ty }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }; - // For example, in `impl Trait`, for all of the bounds on `Assoc`, - // e.g. `type Assoc: OtherTrait`, replace `::Assoc: OtherTrait` - // with `impl Send: OtherTrait`. - for (assoc_pred, assoc_pred_span) in cx - .tcx - .explicit_item_bounds(proj.projection_ty.def_id) - .iter_instantiated_copied(cx.tcx, proj.projection_ty.args) - { - let assoc_pred = assoc_pred.fold_with(proj_replacer); - let Ok(assoc_pred) = traits::fully_normalize( - infcx, - traits::ObligationCause::dummy(), - cx.param_env, - assoc_pred, - ) else { - continue; + let proj_ty = + Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args); + // For every instance of the projection type in the bounds, + // replace them with the term we're assigning to the associated + // type in our opaque type. + let proj_replacer = &mut BottomUpFolder { + tcx: cx.tcx, + ty_op: |ty| if ty == proj_ty { proj_term } else { ty }, + lt_op: |lt| lt, + ct_op: |ct| ct, }; - // If that predicate doesn't hold modulo regions (but passed during type-check), - // then we must've taken advantage of the hack in `project_and_unify_types` where - // we replace opaques with inference vars. Emit a warning! - if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( - cx.tcx, - traits::ObligationCause::dummy(), - cx.param_env, - assoc_pred, - )) { - // If it's a trait bound and an opaque that doesn't satisfy it, - // then we can emit a suggestion to add the bound. - let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { - ( - ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), - ty::ClauseKind::Trait(trait_pred), - ) => Some(AddBound { - suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), - trait_ref: trait_pred.print_modifiers_and_trait_path(), - }), - _ => None, + // For example, in `impl Trait`, for all of the bounds on `Assoc`, + // e.g. `type Assoc: OtherTrait`, replace `::Assoc: OtherTrait` + // with `impl Send: OtherTrait`. + for (assoc_pred, assoc_pred_span) in cx + .tcx + .explicit_item_bounds(proj.projection_ty.def_id) + .iter_instantiated_copied(cx.tcx, proj.projection_ty.args) + { + let assoc_pred = assoc_pred.fold_with(proj_replacer); + let Ok(assoc_pred) = traits::fully_normalize( + infcx, + traits::ObligationCause::dummy(), + cx.param_env, + assoc_pred, + ) else { + continue; }; - cx.emit_span_lint( - OPAQUE_HIDDEN_INFERRED_BOUND, - pred_span, - OpaqueHiddenInferredBoundLint { - ty: Ty::new_opaque( - cx.tcx, - def_id, - ty::GenericArgs::identity_for_item(cx.tcx, def_id), - ), - proj_ty: proj_term, - assoc_pred_span, - add_bound, - }, - ); + + // If that predicate doesn't hold modulo regions (but passed during type-check), + // then we must've taken advantage of the hack in `project_and_unify_types` where + // we replace opaques with inference vars. Emit a warning! + if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( + cx.tcx, + traits::ObligationCause::dummy(), + cx.param_env, + assoc_pred, + )) { + // If it's a trait bound and an opaque that doesn't satisfy it, + // then we can emit a suggestion to add the bound. + let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { + ( + ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), + ty::ClauseKind::Trait(trait_pred), + ) => Some(AddBound { + suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), + trait_ref: trait_pred.print_modifiers_and_trait_path(), + }), + _ => None, + }; + + cx.emit_span_lint( + OPAQUE_HIDDEN_INFERRED_BOUND, + pred_span, + OpaqueHiddenInferredBoundLint { + ty: Ty::new_opaque( + cx.tcx, + def_id, + ty::GenericArgs::identity_for_item(cx.tcx, def_id), + ), + proj_ty: proj_term, + assoc_pred_span, + add_bound, + }, + ); + } } - } + }); } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 927924452f913..8c734fca9b6e7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1052,6 +1052,7 @@ impl<'tcx, T> Binder<'tcx, T> { where T: TypeVisitable>, { + // `self.value` is equivalent to `self.skip_binder()` if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index d02578c484649..daa4977a1e0e7 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -20,7 +20,7 @@ use crate::solve::EvalCtxt; pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result>, NoSolution> { +) -> Result>>, NoSolution> { let tcx = ecx.tcx(); match *ty.kind() { ty::Uint(_) @@ -34,7 +34,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( | ty::Char => Ok(vec![]), // Treat `str` like it's defined as `struct str([u8]);` - ty::Str => Ok(vec![Ty::new_slice(tcx, tcx.types.u8)]), + ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, tcx.types.u8))]), ty::Dynamic(..) | ty::Param(..) @@ -47,46 +47,46 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( } ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => { - Ok(vec![element_ty]) + Ok(vec![ty::Binder::dummy(element_ty)]) } - ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![element_ty]), + ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![ty::Binder::dummy(element_ty)]), ty::Tuple(tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - Ok(tys.iter().collect()) + Ok(tys.iter().map(ty::Binder::dummy).collect()) } - ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), + ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), ty::CoroutineClosure(_, args) => Ok(vec![args.as_coroutine_closure().tupled_upvars_ty()]), ty::Coroutine(_, args) => { let coroutine_args = args.as_coroutine(); - Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]) + Ok(vec![ + ty::Binder::dummy(coroutine_args.tupled_upvars_ty()), + ty::Binder::dummy(coroutine_args.witness()), + ]) } ty::CoroutineWitness(def_id, args) => Ok(ecx .tcx() .coroutine_hidden_types(def_id) - .map(|bty| { - ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars( - tcx, - bty.instantiate(tcx, args), - )) - }) + .map(|bty| replace_erased_lifetimes_with_bound_vars(tcx, bty.instantiate(tcx, args))) .collect()), // For `PhantomData`, we pass `T`. - ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![args.type_at(0)]), + ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]), - ty::Adt(def, args) => Ok(def.all_fields().map(|f| f.ty(tcx, args)).collect()), + ty::Adt(def, args) => { + Ok(def.all_fields().map(|f| ty::Binder::dummy(f.ty(tcx, args))).collect()) + } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. - Ok(vec![tcx.type_of(def_id).instantiate(tcx, args)]) + Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))]) } } } @@ -116,7 +116,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result>, NoSolution> { +) -> Result>>, NoSolution> { match *ty.kind() { ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Uint(_) @@ -150,11 +150,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( bug!("unexpected type `{ty}`") } - ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()), ty::Adt(def, args) => { let sized_crit = def.sized_constraint(ecx.tcx()); - Ok(sized_crit.iter_instantiated(ecx.tcx(), args).collect()) + Ok(sized_crit.iter_instantiated(ecx.tcx(), args).map(ty::Binder::dummy).collect()) } } } @@ -163,7 +163,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result>, NoSolution> { +) -> Result>>, NoSolution> { match *ty.kind() { ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]), @@ -194,9 +194,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( bug!("unexpected type `{ty}`") } - ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()), - ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), + ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), ty::CoroutineClosure(..) => Err(NoSolution), @@ -205,7 +205,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( Movability::Movable => { if ecx.tcx().features().coroutine_clone { let coroutine = args.as_coroutine(); - Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]) + Ok(vec![ + ty::Binder::dummy(coroutine.tupled_upvars_ty()), + ty::Binder::dummy(coroutine.witness()), + ]) } else { Err(NoSolution) } @@ -216,10 +219,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( .tcx() .coroutine_hidden_types(def_id) .map(|bty| { - ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars( + replace_erased_lifetimes_with_bound_vars( ecx.tcx(), bty.instantiate(ecx.tcx(), args), - )) + ) }) .collect()), } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 76c50a111027d..a1c55091c2676 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -477,10 +477,12 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } } else { - let kind = self.infcx.instantiate_binder_with_placeholders(kind); - let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); - self.add_goal(GoalSource::Misc, goal); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.infcx.enter_forall(kind, |kind| { + let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); + self.add_goal(GoalSource::Misc, goal); + // FIXME(tree_universes): leaking universes + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } } @@ -801,13 +803,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) } - pub(super) fn instantiate_binder_with_placeholders> + Copy>( + pub(super) fn enter_forall> + Copy, U>( &self, value: ty::Binder<'tcx, T>, - ) -> T { - self.infcx.instantiate_binder_with_placeholders(value) + f: impl FnOnce(T) -> U, + ) -> U { + self.infcx.enter_forall(value, f) } - pub(super) fn resolve_vars_if_possible(&self, value: T) -> T where T: TypeFoldable>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 315df06be417c..2706b5c8e0d2e 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -31,103 +31,109 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { ) -> SelectionResult<'tcx, Selection<'tcx>> { assert!(self.next_trait_solver()); - let trait_goal = Goal::new( - self.tcx, - obligation.param_env, - self.instantiate_binder_with_placeholders(obligation.predicate), - ); - - let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| { - let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate); - let (orig_values, canonical_goal) = ecx.canonicalize_goal(goal); - let mut candidates = ecx.compute_canonical_trait_candidates(canonical_goal); - - // pseudo-winnow - if candidates.len() == 0 { - return Err(SelectionError::Unimplemented); - } else if candidates.len() > 1 { - let mut i = 0; - while i < candidates.len() { - let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { - candidate_should_be_dropped_in_favor_of( - ecx.tcx(), - &candidates[i], - &candidates[j], - ) - }); - if should_drop_i { - candidates.swap_remove(i); - } else { - i += 1; - if i > 1 { - return Ok(None); + // FIXME(tree_universes): leaking universes? + self.enter_forall(obligation.predicate, |pred| { + let trait_goal = Goal::new(self.tcx, obligation.param_env, pred); + + let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| { + let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate); + let (orig_values, canonical_goal) = ecx.canonicalize_goal(goal); + let mut candidates = ecx.compute_canonical_trait_candidates(canonical_goal); + + // pseudo-winnow + if candidates.len() == 0 { + return Err(SelectionError::Unimplemented); + } else if candidates.len() > 1 { + let mut i = 0; + while i < candidates.len() { + let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { + candidate_should_be_dropped_in_favor_of( + ecx.tcx(), + &candidates[i], + &candidates[j], + ) + }); + if should_drop_i { + candidates.swap_remove(i); + } else { + i += 1; + if i > 1 { + return Ok(None); + } } } } - } - let candidate = candidates.pop().unwrap(); - let (certainty, nested_goals) = ecx - .instantiate_and_apply_query_response( - trait_goal.param_env, - orig_values, - candidate.result, - ) - .map_err(|_| SelectionError::Unimplemented)?; - - Ok(Some((candidate, certainty, nested_goals))) - }); - - let (candidate, certainty, nested_goals) = match result { - Ok(Some((candidate, certainty, nested_goals))) => (candidate, certainty, nested_goals), - Ok(None) => return Ok(None), - Err(e) => return Err(e), - }; - - let nested_obligations: Vec<_> = nested_goals - .into_iter() - .map(|goal| { - Obligation::new(self.tcx, ObligationCause::dummy(), goal.param_env, goal.predicate) - }) - .collect(); - - let goal = self.resolve_vars_if_possible(trait_goal); - match (certainty, candidate.source) { - // Rematching the implementation will instantiate the same nested goals that - // would have caused the ambiguity, so we can still make progress here regardless. - (_, CandidateSource::Impl(def_id)) => { - rematch_impl(self, goal, def_id, nested_obligations) - } + let candidate = candidates.pop().unwrap(); + let (certainty, nested_goals) = ecx + .instantiate_and_apply_query_response( + trait_goal.param_env, + orig_values, + candidate.result, + ) + .map_err(|_| SelectionError::Unimplemented)?; + + Ok(Some((candidate, certainty, nested_goals))) + }); + + let (candidate, certainty, nested_goals) = match result { + Ok(Some((candidate, certainty, nested_goals))) => { + (candidate, certainty, nested_goals) + } + Ok(None) => return Ok(None), + Err(e) => return Err(e), + }; + + let nested_obligations: Vec<_> = nested_goals + .into_iter() + .map(|goal| { + Obligation::new( + self.tcx, + ObligationCause::dummy(), + goal.param_env, + goal.predicate, + ) + }) + .collect(); + + let goal = self.resolve_vars_if_possible(trait_goal); + match (certainty, candidate.source) { + // Rematching the implementation will instantiate the same nested goals that + // would have caused the ambiguity, so we can still make progress here regardless. + (_, CandidateSource::Impl(def_id)) => { + rematch_impl(self, goal, def_id, nested_obligations) + } - // If an unsize goal is ambiguous, then we can manually rematch it to make - // selection progress for coercion during HIR typeck. If it is *not* ambiguous, - // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals, - // and we need to rematch those to detect tuple unsizing and trait upcasting. - // FIXME: This will be wrong if we have param-env or where-clause bounds - // with the unsize goal -- we may need to mark those with different impl - // sources. - (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) - | (Certainty::Yes, CandidateSource::BuiltinImpl(src @ BuiltinImplSource::Misc)) - if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => - { - rematch_unsize(self, goal, nested_obligations, src, certainty) - } + // If an unsize goal is ambiguous, then we can manually rematch it to make + // selection progress for coercion during HIR typeck. If it is *not* ambiguous, + // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals, + // and we need to rematch those to detect tuple unsizing and trait upcasting. + // FIXME: This will be wrong if we have param-env or where-clause bounds + // with the unsize goal -- we may need to mark those with different impl + // sources. + (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) + | (Certainty::Yes, CandidateSource::BuiltinImpl(src @ BuiltinImplSource::Misc)) + if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => + { + rematch_unsize(self, goal, nested_obligations, src, certainty) + } - // Technically some builtin impls have nested obligations, but if - // `Certainty::Yes`, then they should've all been verified and don't - // need re-checking. - (Certainty::Yes, CandidateSource::BuiltinImpl(src)) => { - Ok(Some(ImplSource::Builtin(src, nested_obligations))) - } + // Technically some builtin impls have nested obligations, but if + // `Certainty::Yes`, then they should've all been verified and don't + // need re-checking. + (Certainty::Yes, CandidateSource::BuiltinImpl(src)) => { + Ok(Some(ImplSource::Builtin(src, nested_obligations))) + } - // It's fine not to do anything to rematch these, since there are no - // nested obligations. - (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { - Ok(Some(ImplSource::Param(nested_obligations))) - } + // It's fine not to do anything to rematch these, since there are no + // nested obligations. + (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { + Ok(Some(ImplSource::Param(nested_obligations))) + } - (Certainty::Maybe(_), _) => Ok(None), - } + (Certainty::Maybe(_), _) => Ok(None), + } + }) } } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index fd09a6b671dad..53307da1d9be9 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -1049,14 +1049,22 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { fn probe_and_evaluate_goal_for_constituent_tys( &mut self, goal: Goal<'tcx, TraitPredicate<'tcx>>, - constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result>, NoSolution>, + constituent_tys: impl Fn( + &EvalCtxt<'_, 'tcx>, + Ty<'tcx>, + ) -> Result>>, NoSolution>, ) -> QueryResult<'tcx> { self.probe_misc_candidate("constituent tys").enter(|ecx| { ecx.add_goals( GoalSource::ImplWhereBound, constituent_tys(ecx, goal.predicate.self_ty())? .into_iter() - .map(|ty| goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty))) + .map(|ty| { + // FIXME(tree_universes): leaking universes + ecx.enter_forall(ty, |ty| { + goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty)) + }) + }) .collect::>(), ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 4b20de2621924..cbe9a238b1c28 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -971,7 +971,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { let Goal { param_env, predicate } = goal.goal(); - // For bound predicates we simply call `infcx.instantiate_binder_with_placeholders` + // For bound predicates we simply call `infcx.enter_forall` // and then prove the resulting predicate as a nested goal. let trait_ref = match predicate.kind().no_bound_vars() { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index b246e476bedf9..c6f5af08013e6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -21,51 +21,62 @@ pub fn recompute_applicable_impls<'tcx>( let impl_may_apply = |impl_def_id| { let ocx = ObligationCtxt::new(infcx); - let placeholder_obligation = - infcx.instantiate_binder_with_placeholders(obligation.predicate); - let obligation_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); - - let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args); - let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); - - if let Err(_) = - ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref) - { - return false; - } + infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + let obligation_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + placeholder_obligation.trait_ref, + ); + + let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = + tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args); + let impl_trait_ref = + ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); + + if let Err(_) = + ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref) + { + return false; + } - let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args); - ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| { - Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) - })); + let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args); + ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| { + Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) + })); - ocx.select_where_possible().is_empty() + ocx.select_where_possible().is_empty() + }) }; let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| { let ocx = ObligationCtxt::new(infcx); - let placeholder_obligation = - infcx.instantiate_binder_with_placeholders(obligation.predicate); - let obligation_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); - - let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( - DUMMY_SP, - BoundRegionConversionTime::HigherRankedType, - poly_trait_predicate, - ); - let param_env_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref); - - if let Err(_) = - ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref) - { - return false; - } + infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + let obligation_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + placeholder_obligation.trait_ref, + ); + + let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + poly_trait_predicate, + ); + let param_env_trait_ref = + ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref); + + if let Err(_) = ocx.eq( + &ObligationCause::dummy(), + param_env, + obligation_trait_ref, + param_env_trait_ref, + ) { + return false; + } - ocx.select_where_possible().is_empty() + ocx.select_where_possible().is_empty() + }) }; let mut ambiguities = Vec::new(); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 972da180a3365..ceff718764685 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -64,39 +64,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> Option<(DefId, GenericArgsRef<'tcx>)> { let tcx = self.tcx; let param_env = obligation.param_env; - let trait_ref = self.instantiate_binder_with_placeholders(trait_ref); - let trait_self_ty = trait_ref.self_ty(); + self.enter_forall(trait_ref, |trait_ref| { + let trait_self_ty = trait_ref.self_ty(); - let mut self_match_impls = vec![]; - let mut fuzzy_match_impls = vec![]; + let mut self_match_impls = vec![]; + let mut fuzzy_match_impls = vec![]; - self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| { - let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id); - let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); + self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| { + let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id); + let impl_trait_ref = + tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); - let impl_self_ty = impl_trait_ref.self_ty(); + let impl_self_ty = impl_trait_ref.self_ty(); - if self.can_eq(param_env, trait_self_ty, impl_self_ty) { - self_match_impls.push((def_id, impl_args)); + if self.can_eq(param_env, trait_self_ty, impl_self_ty) { + self_match_impls.push((def_id, impl_args)); - if iter::zip(trait_ref.args.types().skip(1), impl_trait_ref.args.types().skip(1)) + if iter::zip( + trait_ref.args.types().skip(1), + impl_trait_ref.args.types().skip(1), + ) .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some()) - { - fuzzy_match_impls.push((def_id, impl_args)); + { + fuzzy_match_impls.push((def_id, impl_args)); + } } - } - }); + }); - let impl_def_id_and_args = if self_match_impls.len() == 1 { - self_match_impls[0] - } else if fuzzy_match_impls.len() == 1 { - fuzzy_match_impls[0] - } else { - return None; - }; + let impl_def_id_and_args = if self_match_impls.len() == 1 { + self_match_impls[0] + } else if fuzzy_match_impls.len() == 1 { + fuzzy_match_impls[0] + } else { + return None; + }; - tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented) - .then_some(impl_def_id_and_args) + tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented) + .then_some(impl_def_id_and_args) + }) } /// Used to set on_unimplemented's `ItemContext` 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 243f583aed825..046b2718dba88 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1248,52 +1248,55 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); - let ty = self.instantiate_binder_with_placeholders(self_ty); - let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { - return false; - }; - let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; - let ty::Param(param) = inner_ty.kind() else { return false }; - let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = - obligation.cause.code() - else { - return false; - }; - let arg_node = self.tcx.hir_node(*arg_hir_id); - let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { return false }; + self.enter_forall(self_ty, |ty: Ty<'_>| { + let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { + return false; + }; + let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; + let ty::Param(param) = inner_ty.kind() else { return false }; + let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = + obligation.cause.code() + else { + return false; + }; + let arg_node = self.tcx.hir_node(*arg_hir_id); + let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { + return false; + }; - let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); - let has_clone = |ty| { - self.type_implements_trait(clone_trait, [ty], obligation.param_env) - .must_apply_modulo_regions() - }; + let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); + let has_clone = |ty| { + self.type_implements_trait(clone_trait, [ty], obligation.param_env) + .must_apply_modulo_regions() + }; - let new_obligation = self.mk_trait_obligation_with_new_self_ty( - obligation.param_env, - trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), - ); + let new_obligation = self.mk_trait_obligation_with_new_self_ty( + obligation.param_env, + trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), + ); - if self.predicate_may_hold(&new_obligation) && has_clone(ty) { - if !has_clone(param.to_ty(self.tcx)) { - suggest_constraining_type_param( - self.tcx, - generics, - err, - param.name.as_str(), - "Clone", - Some(clone_trait), - None, + if self.predicate_may_hold(&new_obligation) && has_clone(ty) { + if !has_clone(param.to_ty(self.tcx)) { + suggest_constraining_type_param( + self.tcx, + generics, + err, + param.name.as_str(), + "Clone", + Some(clone_trait), + None, + ); + } + err.span_suggestion_verbose( + obligation.cause.span.shrink_to_hi(), + "consider using clone here", + ".clone()".to_string(), + Applicability::MaybeIncorrect, ); + return true; } - err.span_suggestion_verbose( - obligation.cause.span.shrink_to_hi(), - "consider using clone here", - ".clone()", - Applicability::MaybeIncorrect, - ); - return true; - } - false + false + }) } /// Extracts information about a callable type for diagnostics. This is a @@ -4038,26 +4041,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(where_pred) = where_pred.as_trait_clause() && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred() { - let where_pred = self.instantiate_binder_with_placeholders(where_pred); - let failed_pred = self.instantiate_binder_with_fresh_vars( - expr.span, - BoundRegionConversionTime::FnCall, - failed_pred, - ); + self.enter_forall(where_pred, |where_pred| { + let failed_pred = self.instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + failed_pred, + ); - let zipped = iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); - for (expected, actual) in zipped { - self.probe(|_| { - match self.at(&ObligationCause::misc(expr.span, body_id), param_env).eq( - DefineOpaqueTypes::No, - expected, - actual, - ) { - Ok(_) => (), // We ignore nested obligations here for now. - Err(err) => type_diffs.push(err), - } - }) - } + let zipped = + iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); + for (expected, actual) in zipped { + self.probe(|_| { + match self + .at(&ObligationCause::misc(expr.span, body_id), param_env) + .eq(DefineOpaqueTypes::No, expected, actual) + { + Ok(_) => (), // We ignore nested obligations here for now. + Err(err) => type_diffs.push(err), + } + }) + } + }) } else if let Some(where_pred) = where_pred.as_projection_clause() && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred() && let Some(found) = failed_pred.skip_binder().term.ty() @@ -4615,14 +4619,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { self.probe(|_| { let ocx = ObligationCtxt::new(self); - let pred = self.instantiate_binder_with_placeholders(pred); - let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred); - ocx.register_obligation(Obligation::new( - self.tcx, - ObligationCause::dummy(), - param_env, - pred, - )); + self.enter_forall(pred, |pred| { + let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred); + // FIXME(tree_universes): universe leakage + ocx.register_obligation(Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + pred, + )); + }); if !ocx.select_where_possible().is_empty() { // encountered errors. return; @@ -4769,13 +4775,13 @@ fn hint_missing_borrow<'tcx>( } let found_args = match found.kind() { - ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(), + ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()), kind => { span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind) } }; let expected_args = match expected.kind() { - ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(), + ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()), kind => { span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind) } 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 4ef490758a332..0f253981930cd 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 @@ -1307,12 +1307,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut pred = obligation.predicate.to_opt_poly_trait_pred(); while let Some((next_code, next_pred)) = code.parent() { if let Some(pred) = pred { - let pred = self.instantiate_binder_with_placeholders(pred); - diag.note(format!( - "`{}` must implement `{}`, but it does not", - pred.self_ty(), - pred.print_modifiers_and_trait_path() - )); + self.enter_forall(pred, |pred| { + diag.note(format!( + "`{}` must implement `{}`, but it does not", + pred.self_ty(), + pred.print_modifiers_and_trait_path() + )); + }) } code = next_code; pred = next_pred; @@ -2017,70 +2018,79 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let [single] = &impl_candidates { if self.probe(|_| { let ocx = ObligationCtxt::new(self); - let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref); - let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); - let impl_trait_ref = ocx.normalize( - &ObligationCause::dummy(), - param_env, - ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), - ); - ocx.register_obligations( - self.tcx - .predicates_of(single.impl_def_id) - .instantiate(self.tcx, impl_args) - .into_iter() - .map(|(clause, _)| { - Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause) - }), - ); - if !ocx.select_where_possible().is_empty() { - return false; - } + self.enter_forall(trait_ref, |obligation_trait_ref| { + let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); + let impl_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), + ); - let mut terrs = vec![]; - for (obligation_arg, impl_arg) in - std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) - { - if let Err(terr) = - ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg) - { - terrs.push(terr); - } + ocx.register_obligations( + self.tcx + .predicates_of(single.impl_def_id) + .instantiate(self.tcx, impl_args) + .into_iter() + .map(|(clause, _)| { + Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + clause, + ) + }), + ); if !ocx.select_where_possible().is_empty() { return false; } - } - // Literally nothing unified, just give up. - if terrs.len() == impl_trait_ref.args.len() { - return false; - } + let mut terrs = vec![]; + for (obligation_arg, impl_arg) in + std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) + { + // FIXME(tree_universes): universe leakage + if let Err(terr) = + ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg) + { + terrs.push(terr); + } + if !ocx.select_where_possible().is_empty() { + return false; + } + } - let cand = - self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder { - tcx: self.tcx, - ty_op: |ty| ty, - lt_op: |lt| lt, - ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), - }); - err.highlighted_help(vec![ - 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("`"), - ]); + // Literally nothing unified, just give up. + if terrs.len() == impl_trait_ref.args.len() { + return false; + } - if let [TypeError::Sorts(exp_found)] = &terrs[..] { - let exp_found = self.resolve_vars_if_possible(*exp_found); - err.help(format!( - "for that trait implementation, expected `{}`, found `{}`", - exp_found.expected, exp_found.found - )); - } + let cand = self.resolve_vars_if_possible(impl_trait_ref).fold_with( + &mut BottomUpFolder { + tcx: self.tcx, + ty_op: |ty| ty, + lt_op: |lt| lt, + ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), + }, + ); + err.highlighted_help(vec![ + 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[..] { + let exp_found = self.resolve_vars_if_possible(*exp_found); + err.help(format!( + "for that trait implementation, expected `{}`, found `{}`", + exp_found.expected, exp_found.found + )); + } - true + true + }) }) { return true; } diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 3b5e41e8d850e..5e0f15a0d77ff 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -164,7 +164,7 @@ pub enum RegionKind { /// Should not exist outside of type inference. /// /// Used when instantiating a `forall` binder via - /// `infcx.instantiate_binder_with_placeholders`. + /// `infcx.enter_forall` and `infcx.instantiate_binder_with_placeholders`. RePlaceholder(I::PlaceholderRegion), /// Erased region, used by trait selection, in MIR and during codegen. From b181a1262326795a438e0d9118fd71b7bc94c3ae Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 30 Jan 2024 02:15:21 +0000 Subject: [PATCH 656/676] rename `instantiate_binder_with_placeholders` --- compiler/rustc_infer/src/infer/mod.rs | 4 ++-- .../src/infer/relate/higher_ranked.rs | 23 ++++++++++++++++--- compiler/rustc_infer/src/infer/relate/nll.rs | 4 ++-- .../src/solve/fulfill.rs | 4 ++-- .../src/traits/fulfill.rs | 3 +-- .../src/traits/project.rs | 3 +-- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 10 ++++---- .../src/traits/select/mod.rs | 6 ++--- compiler/rustc_type_ir/src/region_kind.rs | 2 +- 10 files changed, 38 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 82690b9acbece..f7969e31dee8f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1032,7 +1032,7 @@ impl<'tcx> InferCtxt<'tcx> { _ => {} } - // FIXME(tree_universes): leaking universes + // FIXME(tree_universes): leaking placeholders self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)) }) @@ -1043,7 +1043,7 @@ impl<'tcx> InferCtxt<'tcx> { cause: &traits::ObligationCause<'tcx>, predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) { - // FIXME(tree_universes): leaking universes + // FIXME(tree_universes): leaking placeholders self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| { let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index cff544ed15400..ff01f620e6680 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -49,11 +49,13 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { debug!("b_prime={:?}", sup_prime); // Compare types now that bound regions have been replaced. - // FIXME(tree_universes): leaked dead universes + // FIXME(tree_universes): leaked universes let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime); if result.is_ok() { debug!("OK result={result:?}"); } + // NOTE: returning the result here would be dangerous as it contains + // placeholders which **must not** be named afterwards. result.map(|_| ()) }) } @@ -68,9 +70,11 @@ impl<'tcx> InferCtxt<'tcx> { /// This is the first step of checking subtyping when higher-ranked things are involved. /// For more details visit the relevant sections of the [rustc dev guide]. /// + /// `enter_forall` should be preferred over this method. + /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[instrument(level = "debug", skip(self), ret)] - pub fn instantiate_binder_with_placeholders(&self, binder: ty::Binder<'tcx, T>) -> T + pub fn enter_forall_and_leak_universe(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable> + Copy, { @@ -106,11 +110,24 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(binder, delegate) } + /// Replaces all bound variables (lifetimes, types, and constants) bound by + /// `binder` with placeholder variables in a new universe. This means that the + /// new placeholders can only be named by inference variables created after + /// this method has been called. + /// + /// This is the first step of checking subtyping when higher-ranked things are involved. + /// For more details visit the relevant sections of the [rustc dev guide]. + /// + /// This method should be preferred over `enter_forall_and_leak_universe`. + /// + /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + #[instrument(level = "debug", skip(self, f))] pub fn enter_forall(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U where T: TypeFoldable> + Copy, { - let value = self.instantiate_binder_with_placeholders(forall); + let value = self.enter_forall_and_leak_universe(forall); + debug!("?value"); f(value) } diff --git a/compiler/rustc_infer/src/infer/relate/nll.rs b/compiler/rustc_infer/src/infer/relate/nll.rs index 7e93ab995dbc6..2760356bcdf3e 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -262,7 +262,7 @@ where } #[instrument(skip(self), level = "debug")] - fn instantiate_binder_with_placeholders(&mut self, binder: ty::Binder<'tcx, T>) -> T + fn enter_forall_and_leak_universe(&mut self, binder: ty::Binder<'tcx, T>) -> T where T: ty::TypeFoldable> + Copy, { @@ -317,7 +317,7 @@ where where T: ty::TypeFoldable> + Copy, { - let value = self.instantiate_binder_with_placeholders(binder); + let value = self.enter_forall_and_leak_universe(binder); f(self, value) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index f08622816ec28..63555a305d855 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -140,7 +140,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ) } ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( + let (a, b) = infcx.enter_forall_and_leak_universe( goal.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(true, a, b); @@ -150,7 +150,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ) } ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( + let (a, b) = infcx.enter_forall_and_leak_universe( goal.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(false, a, b); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 0337672b3027e..5ef7a202a1253 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -358,8 +358,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::Coerce(_) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) => { - let pred = - ty::Binder::dummy(infcx.instantiate_binder_with_placeholders(binder)); + let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder)); ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)])) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 955c81eee6be3..fd8306bbc0b69 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -250,8 +250,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx; let r = infcx.commit_if_ok(|_snapshot| { let old_universe = infcx.universe(); - let placeholder_predicate = - infcx.instantiate_binder_with_placeholders(obligation.predicate); + let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate); let new_universe = infcx.universe(); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 2258e7961038b..a1894de311efc 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -729,7 +729,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|_snapshot| { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); + self.infcx.enter_forall_and_leak_universe(poly_trait_predicate); let self_ty = placeholder_trait_predicate.self_ty(); let principal_trait_ref = match self_ty.kind() { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index c9d06b0f67521..f0c49253dbd7a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -159,7 +159,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref; + self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref; let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let (def_id, args) = match *placeholder_self_ty.kind() { @@ -402,7 +402,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(BuiltinDerivedObligation); let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref); + let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref); let trait_obligations: Vec> = self.impl_or_trait_obligations( &cause, obligation.recursion_depth + 1, @@ -493,7 +493,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); debug!(?obligation, ?index, "confirm_object_candidate"); - let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty()); let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref); let ty::Dynamic(data, ..) = *self_ty.kind() else { @@ -691,7 +691,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(BuiltinDerivedObligation); // Confirm the `type Output: Sized;` bound that is present on `FnOnce` - let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output()); + let output_ty = self.infcx.enter_forall_and_leak_universe(sig.output()); let output_ty = normalize_with_depth_to( self, obligation.param_env, @@ -712,7 +712,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Vec> { debug!(?obligation, "confirm_trait_alias_candidate"); - let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let args = trait_ref.args; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7f41c73b72f0d..14192c6ddd3d5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1606,7 +1606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> smallvec::SmallVec<[usize; 2]> { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); + self.infcx.enter_forall_and_leak_universe(poly_trait_predicate); debug!(?placeholder_trait_predicate); let tcx = self.infcx.tcx; @@ -2386,7 +2386,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { .flat_map(|ty| { let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/ - let placeholder_ty = self.infcx.instantiate_binder_with_placeholders(ty); + let placeholder_ty = self.infcx.enter_forall_and_leak_universe(ty); let Normalized { value: normalized_ty, mut obligations } = ensure_sufficient_stack(|| { project::normalize_with_depth( @@ -2472,7 +2472,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligation: &PolyTraitObligation<'tcx>, ) -> Result>, ()> { let placeholder_obligation = - self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + self.infcx.enter_forall_and_leak_universe(obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 5e0f15a0d77ff..a85e86f41ac55 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -164,7 +164,7 @@ pub enum RegionKind { /// Should not exist outside of type inference. /// /// Used when instantiating a `forall` binder via - /// `infcx.enter_forall` and `infcx.instantiate_binder_with_placeholders`. + /// `infcx.enter_forall` and `infcx.enter_forall_and_leak_universe`. RePlaceholder(I::PlaceholderRegion), /// Erased region, used by trait selection, in MIR and during codegen. From f867742be8a19ca253b0d7d1c9a4ab54b7ff02c5 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 8 Feb 2024 13:19:20 +0000 Subject: [PATCH 657/676] reviews + rebase --- compiler/rustc_infer/src/infer/mod.rs | 2 - .../src/infer/relate/higher_ranked.rs | 15 +-- compiler/rustc_infer/src/infer/relate/nll.rs | 89 ++++++++--------- .../src/solve/assembly/structural_traits.rs | 4 +- .../src/solve/eval_ctxt/mod.rs | 1 - .../src/solve/eval_ctxt/select.rs | 1 - .../src/solve/trait_goals.rs | 1 - .../src/traits/error_reporting/suggestions.rs | 1 - .../error_reporting/type_err_ctxt_ext.rs | 1 - .../src/traits/select/candidate_assembly.rs | 97 +++++++++---------- compiler/rustc_type_ir/src/region_kind.rs | 3 +- 11 files changed, 101 insertions(+), 114 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f7969e31dee8f..2d87f01ff104f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1032,7 +1032,6 @@ impl<'tcx> InferCtxt<'tcx> { _ => {} } - // FIXME(tree_universes): leaking placeholders self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)) }) @@ -1043,7 +1042,6 @@ impl<'tcx> InferCtxt<'tcx> { cause: &traits::ObligationCause<'tcx>, predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) { - // FIXME(tree_universes): leaking placeholders self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| { let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index ff01f620e6680..90be80f67b4d0 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -49,7 +49,6 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { debug!("b_prime={:?}", sup_prime); // Compare types now that bound regions have been replaced. - // FIXME(tree_universes): leaked universes let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime); if result.is_ok() { debug!("OK result={result:?}"); @@ -70,7 +69,7 @@ impl<'tcx> InferCtxt<'tcx> { /// This is the first step of checking subtyping when higher-ranked things are involved. /// For more details visit the relevant sections of the [rustc dev guide]. /// - /// `enter_forall` should be preferred over this method. + /// `fn enter_forall` should be preferred over this method. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[instrument(level = "debug", skip(self), ret)] @@ -111,14 +110,14 @@ impl<'tcx> InferCtxt<'tcx> { } /// Replaces all bound variables (lifetimes, types, and constants) bound by - /// `binder` with placeholder variables in a new universe. This means that the - /// new placeholders can only be named by inference variables created after - /// this method has been called. + /// `binder` with placeholder variables in a new universe and then calls the + /// closure `f` with the instantiated value. The new placeholders can only be + /// named by inference variables created inside of the closure `f` or afterwards. /// /// This is the first step of checking subtyping when higher-ranked things are involved. /// For more details visit the relevant sections of the [rustc dev guide]. /// - /// This method should be preferred over `enter_forall_and_leak_universe`. + /// This method should be preferred over `fn enter_forall_and_leak_universe`. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[instrument(level = "debug", skip(self, f))] @@ -126,6 +125,10 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable> + Copy, { + // FIXME: currently we do nothing to prevent placeholders with the new universe being + // used after exiting `f`. For example region subtyping can result in outlives constraints + // that name placeholders created in this function. Nested goals from type relations can + // also contain placeholders created by this function. let value = self.enter_forall_and_leak_universe(forall); debug!("?value"); f(value) diff --git a/compiler/rustc_infer/src/infer/relate/nll.rs b/compiler/rustc_infer/src/infer/relate/nll.rs index 2760356bcdf3e..5e2d2af9b8587 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -261,54 +261,6 @@ where Ok(a) } - #[instrument(skip(self), level = "debug")] - fn enter_forall_and_leak_universe(&mut self, binder: ty::Binder<'tcx, T>) -> T - where - T: ty::TypeFoldable> + Copy, - { - if let Some(inner) = binder.no_bound_vars() { - return inner; - } - - let mut next_region = { - let nll_delegate = &mut self.delegate; - let mut lazy_universe = None; - - move |br: ty::BoundRegion| { - // The first time this closure is called, create a - // new universe for the placeholders we will make - // from here out. - let universe = lazy_universe.unwrap_or_else(|| { - let universe = nll_delegate.create_next_universe(); - lazy_universe = Some(universe); - universe - }); - - let placeholder = ty::PlaceholderRegion { universe, bound: br }; - debug!(?placeholder); - let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); - debug!(?placeholder_reg); - - placeholder_reg - } - }; - - let delegate = FnMutDelegate { - regions: &mut next_region, - types: &mut |_bound_ty: ty::BoundTy| { - unreachable!("we only replace regions in nll_relate, not types") - }, - consts: &mut |_bound_var: ty::BoundVar, _ty| { - unreachable!("we only replace regions in nll_relate, not consts") - }, - }; - - let replaced = self.infcx.tcx.replace_bound_vars_uncached(binder, delegate); - debug!(?replaced); - - replaced - } - fn enter_forall( &mut self, binder: ty::Binder<'tcx, T>, @@ -317,7 +269,46 @@ where where T: ty::TypeFoldable> + Copy, { - let value = self.enter_forall_and_leak_universe(binder); + let value = if let Some(inner) = binder.no_bound_vars() { + inner + } else { + let mut next_region = { + let nll_delegate = &mut self.delegate; + let mut lazy_universe = None; + + move |br: ty::BoundRegion| { + // The first time this closure is called, create a + // new universe for the placeholders we will make + // from here out. + let universe = lazy_universe.unwrap_or_else(|| { + let universe = nll_delegate.create_next_universe(); + lazy_universe = Some(universe); + universe + }); + + let placeholder = ty::PlaceholderRegion { universe, bound: br }; + debug!(?placeholder); + let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); + debug!(?placeholder_reg); + + placeholder_reg + } + }; + + let delegate = FnMutDelegate { + regions: &mut next_region, + types: &mut |_bound_ty: ty::BoundTy| { + unreachable!("we only replace regions in nll_relate, not types") + }, + consts: &mut |_bound_var: ty::BoundVar, _ty| { + unreachable!("we only replace regions in nll_relate, not consts") + }, + }; + + self.infcx.tcx.replace_bound_vars_uncached(binder, delegate) + }; + + debug!(?value); f(self, value) } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index daa4977a1e0e7..8dec04e2c4f28 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -59,7 +59,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), - ty::CoroutineClosure(_, args) => Ok(vec![args.as_coroutine_closure().tupled_upvars_ty()]), + ty::CoroutineClosure(_, args) => { + Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())]) + } ty::Coroutine(_, args) => { let coroutine_args = args.as_coroutine(); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index a1c55091c2676..803379af005f9 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -480,7 +480,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { self.infcx.enter_forall(kind, |kind| { let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); self.add_goal(GoalSource::Misc, goal); - // FIXME(tree_universes): leaking universes self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 2706b5c8e0d2e..69b6993043268 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -31,7 +31,6 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { ) -> SelectionResult<'tcx, Selection<'tcx>> { assert!(self.next_trait_solver()); - // FIXME(tree_universes): leaking universes? self.enter_forall(obligation.predicate, |pred| { let trait_goal = Goal::new(self.tcx, obligation.param_env, pred); diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 53307da1d9be9..044832224e5c1 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -1060,7 +1060,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { constituent_tys(ecx, goal.predicate.self_ty())? .into_iter() .map(|ty| { - // FIXME(tree_universes): leaking universes ecx.enter_forall(ty, |ty| { goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty)) }) 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 046b2718dba88..5410a74199cfb 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -4621,7 +4621,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let ocx = ObligationCtxt::new(self); self.enter_forall(pred, |pred| { let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred); - // FIXME(tree_universes): universe leakage ocx.register_obligation(Obligation::new( self.tcx, ObligationCause::dummy(), 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 0f253981930cd..6d787a0ea6e9f 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 @@ -2049,7 +2049,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { for (obligation_arg, impl_arg) in std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) { - // FIXME(tree_universes): universe leakage if let Err(terr) = ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg) { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index a1894de311efc..d056dd51f507e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -728,64 +728,63 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|_snapshot| { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); - let placeholder_trait_predicate = - self.infcx.enter_forall_and_leak_universe(poly_trait_predicate); - - let self_ty = placeholder_trait_predicate.self_ty(); - let principal_trait_ref = match self_ty.kind() { - ty::Dynamic(data, ..) => { - if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { - debug!( - "assemble_candidates_from_object_ty: matched builtin bound, \ + self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| { + let self_ty = placeholder_trait_predicate.self_ty(); + let principal_trait_ref = match self_ty.kind() { + ty::Dynamic(data, ..) => { + if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { + debug!( + "assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate" - ); - candidates.vec.push(BuiltinObjectCandidate); - return; - } + ); + candidates.vec.push(BuiltinObjectCandidate); + return; + } - if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().object_safe_for_dispatch { - principal.with_self_ty(self.tcx(), self_ty) - } else if self.tcx().check_is_object_safe(principal.def_id()) { - principal.with_self_ty(self.tcx(), self_ty) + if let Some(principal) = data.principal() { + if !self.infcx.tcx.features().object_safe_for_dispatch { + principal.with_self_ty(self.tcx(), self_ty) + } else if self.tcx().check_is_object_safe(principal.def_id()) { + principal.with_self_ty(self.tcx(), self_ty) + } else { + return; + } } else { + // Only auto trait bounds exist. return; } - } else { - // Only auto trait bounds exist. + } + ty::Infer(ty::TyVar(_)) => { + debug!("assemble_candidates_from_object_ty: ambiguous"); + candidates.ambiguous = true; // could wind up being an object type return; } - } - ty::Infer(ty::TyVar(_)) => { - debug!("assemble_candidates_from_object_ty: ambiguous"); - candidates.ambiguous = true; // could wind up being an object type - return; - } - _ => return, - }; - - debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); - - // Count only those upcast versions that match the trait-ref - // we are looking for. Specifically, do not only check for the - // correct trait, but also the correct type parameters. - // For example, we may be trying to upcast `Foo` to `Bar`, - // but `Foo` is declared as `trait Foo: Bar`. - let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) - .enumerate() - .filter(|&(_, upcast_trait_ref)| { - self.infcx.probe(|_| { - self.match_normalize_trait_ref( - obligation, - upcast_trait_ref, - placeholder_trait_predicate.trait_ref, - ) - .is_ok() + _ => return, + }; + + debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); + + // Count only those upcast versions that match the trait-ref + // we are looking for. Specifically, do not only check for the + // correct trait, but also the correct type parameters. + // For example, we may be trying to upcast `Foo` to `Bar`, + // but `Foo` is declared as `trait Foo: Bar`. + let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) + .enumerate() + .filter(|&(_, upcast_trait_ref)| { + self.infcx.probe(|_| { + self.match_normalize_trait_ref( + obligation, + upcast_trait_ref, + placeholder_trait_predicate.trait_ref, + ) + .is_ok() + }) }) - }) - .map(|(idx, _)| ObjectCandidate(idx)); + .map(|(idx, _)| ObjectCandidate(idx)); - candidates.vec.extend(candidate_supertraits); + candidates.vec.extend(candidate_supertraits); + }) }) } diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index a85e86f41ac55..777c649fabd68 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -163,8 +163,7 @@ pub enum RegionKind { /// A placeholder region -- the higher-ranked version of `ReLateParam`. /// Should not exist outside of type inference. /// - /// Used when instantiating a `forall` binder via - /// `infcx.enter_forall` and `infcx.enter_forall_and_leak_universe`. + /// Used when instantiating a `forall` binder via `infcx.enter_forall`. RePlaceholder(I::PlaceholderRegion), /// Erased region, used by trait selection, in MIR and during codegen. From 6af2d3cc90f7625ad3db4687a93abebfa9e8396a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 8 Feb 2024 14:44:52 +0000 Subject: [PATCH 658/676] Fix `span_bug!` backtraces --- compiler/rustc_errors/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9c5a91adfa091..b6f8dab7e1a22 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -847,6 +847,7 @@ impl DiagCtxt { self.struct_span_warn(span, msg).emit() } + #[track_caller] pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { self.struct_span_bug(span, msg).emit() } From 7dc182d5d405a08ecdb4d652e10c6b6f183d61e7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 8 Feb 2024 14:49:27 +0000 Subject: [PATCH 659/676] Fix mir pass ICE in the presence of other errors --- compiler/rustc_mir_transform/src/abort_unwinding_calls.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 451d3be255fdf..ba70a4453d659 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -41,6 +41,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { ty::Closure(..) => Abi::RustCall, ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + ty::Error(_) => return, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi); From 5cb9e318c81942ebb69f329f205f7a6ee82b6258 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Thu, 8 Feb 2024 11:01:33 -0500 Subject: [PATCH 660/676] Add release note for new ambiguous_wide_pointer_comparisons lint --- RELEASES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASES.md b/RELEASES.md index 038a83cde84d6..3751b15b361b1 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -8,6 +8,7 @@ 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/) +- [Add lint `ambiguous_wide_pointer_comparisons` that supersedes `clippy::vtable_address_comparisons`](https://github.com/rust-lang/rust/pull/117758) From 9842a5ca7ff99916fe866f70833fb9dfd9031e23 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:23:52 -0500 Subject: [PATCH 661/676] Don't lower assume in unoptimized builds --- compiler/rustc_codegen_ssa/src/mir/statement.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index a158fc6e26074..ac7dfbb261dec 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,5 +1,6 @@ use rustc_middle::mir; use rustc_middle::mir::NonDivergingIntrinsic; +use rustc_session::config::OptLevel; use super::FunctionCx; use super::LocalRef; @@ -67,8 +68,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_coverage(bx, coverage, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { - let op_val = self.codegen_operand(bx, op); - bx.assume(op_val.immediate()); + if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) { + let op_val = self.codegen_operand(bx, op); + bx.assume(op_val.immediate()); + } } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( mir::CopyNonOverlapping { ref count, ref src, ref dst }, From 580067c76f0f5b8b356c202c8fce939325f63f29 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:24:23 -0500 Subject: [PATCH 662/676] InstSimplify rustc_nounwind calls --- .../rustc_mir_transform/src/instsimplify.rs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index a28db0defc993..f65eb5cbea938 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -2,10 +2,12 @@ use crate::simplify::simplify_duplicate_switch_targets; use rustc_middle::mir::*; +use rustc_middle::ty::layout; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt}; use rustc_span::symbol::Symbol; use rustc_target::abi::FieldIdx; +use rustc_target::spec::abi::Abi; pub struct InstSimplify; @@ -38,6 +40,7 @@ impl<'tcx> MirPass<'tcx> for InstSimplify { block.terminator.as_mut().unwrap(), &mut block.statements, ); + ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap()); simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); } } @@ -252,6 +255,28 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { terminator.kind = TerminatorKind::Goto { target: destination_block }; } + fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { + let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else { + return; + }; + + let Some((def_id, _)) = func.const_fn_def() else { + return; + }; + + let body_ty = self.tcx.type_of(def_id).skip_binder(); + let body_abi = match body_ty.kind() { + ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(), + ty::Closure(..) => Abi::RustCall, + ty::Coroutine(..) => Abi::Rust, + _ => bug!("unexpected body ty: {:?}", body_ty), + }; + + if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) { + *unwind = UnwindAction::Unreachable; + } + } + fn simplify_intrinsic_assert( &self, terminator: &mut Terminator<'tcx>, From 55fabf35b1069e071e46a153896d897829268db9 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:25:32 -0500 Subject: [PATCH 663/676] Add a new debug_assertions intrinsic --- library/core/src/intrinsics.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 6ea80c8d42faa..7ff9730254cb3 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2569,6 +2569,17 @@ extern "rust-intrinsic" { #[rustc_nounwind] #[cfg(not(bootstrap))] pub fn is_val_statically_known(arg: T) -> bool; + + #[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] + #[rustc_safe_intrinsic] + #[cfg(not(bootstrap))] + pub(crate) fn debug_assertions() -> bool; +} + +#[cfg(bootstrap)] +#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] +pub(crate) const fn debug_assertions() -> bool { + cfg!(debug_assertions) } // FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable` From 8836ac5758c1a470c73798eeae845556e7294f67 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:26:00 -0500 Subject: [PATCH 664/676] Add a new debug_assertions instrinsic (compiler) And in clippy --- compiler/rustc_borrowck/src/type_check/mod.rs | 1 + compiler/rustc_codegen_cranelift/src/base.rs | 9 +++++++++ compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 14 +++++++++---- .../rustc_const_eval/src/interpret/step.rs | 20 +++++++++++++++---- .../src/transform/check_consts/check.rs | 5 ++++- .../src/transform/validate.rs | 2 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 5 ++++- compiler/rustc_middle/src/mir/pretty.rs | 1 + compiler/rustc_middle/src/mir/syntax.rs | 2 ++ compiler/rustc_middle/src/mir/tcx.rs | 1 + .../src/move_paths/builder.rs | 5 ++++- .../src/const_prop_lint.rs | 1 + compiler/rustc_mir_transform/src/gvn.rs | 1 + .../src/lower_intrinsics.rs | 11 ++++++++++ .../rustc_mir_transform/src/promote_consts.rs | 1 + .../rustc_smir/src/rustc_smir/convert/mir.rs | 1 + compiler/stable_mir/src/mir/body.rs | 3 +++ .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- 18 files changed, 72 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index fd20d35220306..1c883f4c62145 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1984,6 +1984,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::SizedBound, ); } + &Rvalue::NullaryOp(NullOp::DebugAssertions, _) => {} Rvalue::ShallowInitBox(operand, ty) => { self.check_operand(operand, location); diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 0afd6d0e670b3..a7e76fbc128ea 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -767,6 +767,15 @@ fn codegen_stmt<'tcx>( NullOp::OffsetOf(fields) => { layout.offset_of_subfield(fx, fields.iter()).bytes() } + NullOp::DebugAssertions => { + let val = fx.tcx.sess.opts.debug_assertions; + let val = CValue::by_val( + fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()), + fx.layout_of(fx.tcx.types.bool), + ); + lval.write_cvalue(fx, val); + return; + } }; let val = CValue::by_val( fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()), diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 266505d3f2691..5c6060a7159aa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -672,17 +672,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = match null_op { mir::NullOp::SizeOf => { assert!(bx.cx().type_is_sized(ty)); - layout.size.bytes() + let val = layout.size.bytes(); + bx.cx().const_usize(val) } mir::NullOp::AlignOf => { assert!(bx.cx().type_is_sized(ty)); - layout.align.abi.bytes() + let val = layout.align.abi.bytes(); + bx.cx().const_usize(val) } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(bx.cx(), fields.iter()).bytes() + let val = layout.offset_of_subfield(bx.cx(), fields.iter()).bytes(); + bx.cx().const_usize(val) + } + mir::NullOp::DebugAssertions => { + let val = bx.tcx().sess.opts.debug_assertions; + bx.cx().const_bool(val) } }; - let val = bx.cx().const_usize(val); let tcx = self.cx.tcx(); OperandRef { val: OperandValue::Immediate(val), diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index d48329b6c6946..f0f1008aba80b 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -246,13 +246,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); } let val = match null_op { - mir::NullOp::SizeOf => layout.size.bytes(), - mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::SizeOf => { + let val = layout.size.bytes(); + Scalar::from_target_usize(val, self) + } + mir::NullOp::AlignOf => { + let val = layout.align.abi.bytes(); + Scalar::from_target_usize(val, self) + } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(self, fields.iter()).bytes() + let val = layout.offset_of_subfield(self, fields.iter()).bytes(); + Scalar::from_target_usize(val, self) + } + mir::NullOp::DebugAssertions => { + // The checks hidden behind this are always better done by the interpreter + // itself, because it knows the runtime state better. + Scalar::from_bool(false) } }; - self.write_scalar(Scalar::from_target_usize(val, self), &dest)?; + self.write_scalar(val, &dest)?; } ShallowInitBox(ref operand, _) => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 5ff81615552bf..ee3f349c6b83c 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -544,7 +544,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Cast(_, _, _) => {} - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {} + Rvalue::NullaryOp( + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, + _, + ) => {} Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, operand) => { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index c4542aaa7b2fb..db4d2be5470e1 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -1139,7 +1139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) | Rvalue::AddressOf(_, _) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::DebugAssertions, _) | Rvalue::Discriminant(_) => {} } self.super_rvalue(rvalue, location); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 2d0d6611444c5..96b0cffc8a3d4 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -112,7 +112,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir | sym::forget | sym::black_box | sym::variant_count - | sym::ptr_mask => hir::Unsafety::Normal, + | sym::ptr_mask + | sym::debug_assertions => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, }; @@ -461,6 +462,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize) } + sym::debug_assertions => (0, Vec::new(), tcx.types.bool), + other => { tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other }); return; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 6f587fdd53c61..b601b465668e9 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -907,6 +907,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { NullOp::SizeOf => write!(fmt, "SizeOf({t})"), NullOp::AlignOf => write!(fmt, "AlignOf({t})"), NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"), + NullOp::DebugAssertions => write!(fmt, "cfg!(debug_assertions)"), } } ThreadLocalRef(did) => ty::tls::with(|tcx| { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index ca56e1fd92c6b..40af453f6ce6f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1361,6 +1361,8 @@ pub enum NullOp<'tcx> { AlignOf, /// Returns the offset of a field OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>), + /// cfg!(debug_assertions), but expanded in codegen + DebugAssertions, } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 4780042a51090..5bc151de659c3 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -194,6 +194,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { tcx.types.usize } + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => tcx.types.bool, Rvalue::Aggregate(ref ak, ref ops) => match **ak { AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), AggregateKind::Tuple => { diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 30dd915521cd2..80e0d0baf5786 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -429,7 +429,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {} + | Rvalue::NullaryOp( + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::DebugAssertions, + _, + ) => {} } } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index f2448ee3d44af..4dccc01d041f8 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -639,6 +639,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { NullOp::OffsetOf(fields) => { op_layout.offset_of_subfield(self, fields.iter()).bytes() } + NullOp::DebugAssertions => return None, }; ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into() } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 6e4f8f710b683..36c441a394536 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -489,6 +489,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { NullOp::OffsetOf(fields) => { layout.offset_of_subfield(&self.ecx, fields.iter()).bytes() } + NullOp::DebugAssertions => return None, }; let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); let imm = ImmTy::try_from_uint(val, usize_layout)?; diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 897375e0e1645..f43b85173d428 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -21,6 +21,17 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { sym::unreachable => { terminator.kind = TerminatorKind::Unreachable; } + sym::debug_assertions => { + let target = target.unwrap(); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::NullaryOp(NullOp::DebugAssertions, tcx.types.bool), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; + } sym::forget => { if let Some(target) = *target { block.statements.push(Statement { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index c00093ea27edd..577b8f2080fcd 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -446,6 +446,7 @@ impl<'tcx> Validator<'_, 'tcx> { NullOp::SizeOf => {} NullOp::AlignOf => {} NullOp::OffsetOf(_) => {} + NullOp::DebugAssertions => {} }, Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 41a4edfc03b58..501d6f7d304ef 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -257,6 +257,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf( indices.iter().map(|idx| idx.stable(tables)).collect(), ), + DebugAssertions => stable_mir::mir::NullOp::DebugAssertions, } } } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 38877f7a77fc4..be727f024c609 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -639,6 +639,7 @@ impl Rvalue { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { Ok(Ty::usize_ty()) } + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => Ok(Ty::bool_ty()), Rvalue::Aggregate(ak, ops) => match *ak { AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64), AggregateKind::Tuple => Ok(Ty::new_tuple( @@ -1005,6 +1006,8 @@ pub enum NullOp { AlignOf, /// Returns the offset of a field. OffsetOf(Vec<(VariantIdx, FieldIdx)>), + /// cfg!(debug_assertions), but at codegen time + DebugAssertions, } impl Operand { diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 81f4fcc2133d1..8d5bcd665ad25 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -174,7 +174,7 @@ fn check_rvalue<'tcx>( )) } }, - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) | Rvalue::ShallowInitBox(_, _) => { + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, _) | Rvalue::ShallowInitBox(_, _) => { Ok(()) }, Rvalue::UnaryOp(_, operand) => { From 61118ffd04aa6d1f9ee92daae4deb28bd975d4ab Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:27:57 -0500 Subject: [PATCH 665/676] Rewrite assert_unsafe_precondition around the new intrinsic --- library/core/src/char/convert.rs | 2 +- library/core/src/hint.rs | 2 +- library/core/src/intrinsics.rs | 123 +++++++++++++++++++++--------- library/core/src/ptr/const_ptr.rs | 8 +- library/core/src/ptr/mod.rs | 45 ++++++++--- library/core/src/ptr/non_null.rs | 5 +- library/core/src/slice/raw.rs | 21 ++++- 7 files changed, 147 insertions(+), 59 deletions(-) diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 177f39b59aed7..7bd592492a5c3 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -27,7 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char { unsafe { assert_unsafe_precondition!( "invalid value for `char`", - (i: u32) => char_try_from_u32(i).is_ok() + (i: u32 = i) => char_try_from_u32(i).is_ok() ); transmute(i) } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 5c44ca69451dd..97c3c9e6fae95 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -148,7 +148,7 @@ pub const unsafe fn assert_unchecked(cond: bool) { unsafe { intrinsics::assert_unsafe_precondition!( "hint::assert_unchecked must never be called when the condition is false", - (cond: bool) => cond, + (cond: bool = cond) => cond, ); crate::intrinsics::assume(cond); } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 7ff9730254cb3..a6311e416333b 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -56,7 +56,7 @@ use crate::marker::DiscriminantKind; use crate::marker::Tuple; -use crate::mem; +use crate::mem::{self, align_of}; pub mod mir; pub mod simd; @@ -2598,10 +2598,27 @@ pub const unsafe fn is_val_statically_known(_arg: T) -> bool { /// Check that the preconditions of an unsafe function are followed, if debug_assertions are on, /// and only at runtime. /// -/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)` -/// where the names specified will be moved into the macro as captured variables, and defines an item -/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics -/// for the function declarations and can be omitted if there is no generics. +/// This macro should be called as +/// `assert_unsafe_precondition!((expr => name: Type, expr => name: Type) => Expression)` +/// where each `expr` will be evaluated and passed in as function argument `name: Type`. Then all +/// those arguments are passed to a function via [`const_eval_select`]. +/// +/// These checks are behind a condition which is evaluated at codegen time, not expansion time like +/// [`debug_assert`]. This means that a standard library built with optimizations and debug +/// assertions disabled will have these checks optimized out of its monomorphizations, but if a +/// a caller of the standard library has debug assertions enabled and monomorphizes an expansion of +/// this macro, that monomorphization will contain the check. +/// +/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and +/// implementation to mitigate their compile-time overhead. The runtime function that we +/// [`const_eval_select`] to is monomorphic, `#[inline(never)]`, and `#[rustc_nounwind]`. That +/// combination of properties ensures that the code for the checks is only compiled once, and has a +/// minimal impact on the caller's code size. +/// +/// Caller should also introducing any other `let` bindings or any code outside this macro in order +/// to call it. Since the precompiled standard library is built with full debuginfo and these +/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough +/// debuginfo to have a measurable compile-time impact on debug builds. /// /// # Safety /// @@ -2615,26 +2632,24 @@ pub const unsafe fn is_val_statically_known(_arg: T) -> bool { /// /// So in a sense it is UB if this macro is useful, but we expect callers of `unsafe fn` to make /// the occasional mistake, and this check should help them figure things out. -#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn +#[allow_internal_unstable(const_eval_select, delayed_debug_assertions)] // permit this to be called in stably-const fn macro_rules! assert_unsafe_precondition { - ($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => { - if cfg!(debug_assertions) { - // allow non_snake_case to allow capturing const generics - #[allow(non_snake_case)] - #[inline(always)] - fn runtime$(<$($tt)*>)?($($i:$ty),*) { + ($message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => { + { + #[inline(never)] + #[rustc_nounwind] + fn precondition_check($($name:$ty),*) { if !$e { - // don't unwind to reduce impact on code size ::core::panicking::panic_nounwind( - concat!("unsafe precondition(s) violated: ", $name) + concat!("unsafe precondition(s) violated: ", $message) ); } } - #[allow(non_snake_case)] - #[inline] - const fn comptime$(<$($tt)*>)?($(_:$ty),*) {} + const fn comptime($(_:$ty),*) {} - ::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime); + if ::core::intrinsics::debug_assertions() { + ::core::intrinsics::const_eval_select(($($arg,)*), comptime, precondition_check); + } } }; } @@ -2643,30 +2658,47 @@ pub(crate) use assert_unsafe_precondition; /// Checks whether `ptr` is properly aligned with respect to /// `align_of::()`. #[inline] -pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { - !ptr.is_null() && ptr.is_aligned() +pub(crate) fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool { + !ptr.is_null() && ptr.is_aligned_to(align) } -/// Checks whether an allocation of `len` instances of `T` exceeds -/// the maximum allowed allocation size. #[inline] -pub(crate) fn is_valid_allocation_size(len: usize) -> bool { - let max_len = const { - let size = crate::mem::size_of::(); - if size == 0 { usize::MAX } else { isize::MAX as usize / size } - }; +pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool { + let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size }; len <= max_len } +pub(crate) fn is_nonoverlapping_mono( + src: *const (), + dst: *const (), + size: usize, + count: usize, +) -> bool { + let src_usize = src.addr(); + let dst_usize = dst.addr(); + let Some(size) = size.checked_mul(count) else { + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::() * count` overflows a usize", + ) + }; + let diff = src_usize.abs_diff(dst_usize); + // If the absolute distance between the ptrs is at least as big as the size of the buffer, + // they do not overlap. + diff >= size +} + /// Checks whether the regions of memory starting at `src` and `dst` of size /// `count * size_of::()` do *not* overlap. #[inline] pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { let src_usize = src.addr(); let dst_usize = dst.addr(); - let size = mem::size_of::() - .checked_mul(count) - .expect("is_nonoverlapping: `size_of::() * count` overflows a usize"); + let Some(size) = mem::size_of::().checked_mul(count) else { + // Use panic_nounwind instead of Option::expect, so that this function is nounwind. + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::() * count` overflows a usize", + ) + }; let diff = src_usize.abs_diff(dst_usize); // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. @@ -2777,10 +2809,16 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us assert_unsafe_precondition!( "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ and the specified memory ranges do not overlap", - [T](src: *const T, dst: *mut T, count: usize) => - is_aligned_and_not_null(src) - && is_aligned_and_not_null(dst) - && is_nonoverlapping(src, dst, count) + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + count: usize = count, + ) => + is_aligned_and_not_null(src, align) + && is_aligned_and_not_null(dst, align) + && is_nonoverlapping_mono(src, dst, size, count) ); copy_nonoverlapping(src, dst, count) } @@ -2870,9 +2908,15 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { assert_unsafe_precondition!( - "ptr::copy requires that both pointer arguments are aligned and non-null", - [T](src: *const T, dst: *mut T) => - is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) + "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ + and the specified memory ranges do not overlap", + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => + is_aligned_and_not_null(src, align) + && is_aligned_and_not_null(dst, align) ); copy(src, dst, count) } @@ -2945,7 +2989,10 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { unsafe { assert_unsafe_precondition!( "ptr::write_bytes requires that the destination pointer is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *const () = dst as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); write_bytes(dst, val, count) } diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 1d5d683fa16cc..c5e3df07a1cf7 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -806,13 +806,15 @@ impl *const T { where T: Sized, { - let this = self; // SAFETY: The comparison has no side-effects, and the intrinsic // does this check internally in the CTFE implementation. unsafe { assert_unsafe_precondition!( - "ptr::sub_ptr requires `this >= origin`", - [T](this: *const T, origin: *const T) => this >= origin + "ptr::sub_ptr requires `self >= origin`", + ( + this: *const () = self as *const (), + origin: *const () = origin as *const (), + ) => this >= origin ) }; diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index bc05b5b07def3..0fb9017e6d941 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -381,11 +381,11 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash; use crate::intrinsics::{ - self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping, + self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping_mono, }; use crate::marker::FnPtr; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, align_of, size_of, MaybeUninit}; mod alignment; #[unstable(feature = "ptr_alignment_type", issue = "102070")] @@ -967,10 +967,16 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { assert_unsafe_precondition!( "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \ and the specified memory ranges do not overlap", - [T](x: *mut T, y: *mut T, count: usize) => - is_aligned_and_not_null(x) - && is_aligned_and_not_null(y) - && is_nonoverlapping(x, y, count) + ( + x: *mut () = x as *mut (), + y: *mut () = y as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + count: usize = count, + ) => + is_aligned_and_not_null(x, align) + && is_aligned_and_not_null(y, align) + && is_nonoverlapping_mono(x, y, size, count) ); } @@ -1061,7 +1067,10 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { unsafe { assert_unsafe_precondition!( "ptr::replace requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *const () = dst as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); mem::swap(&mut *dst, &mut src); // cannot overlap } @@ -1207,9 +1216,13 @@ pub const unsafe fn read(src: *const T) -> T { // SAFETY: the caller must guarantee that `src` is valid for reads. unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) assert_unsafe_precondition!( "ptr::read requires that the pointer argument is aligned and non-null", - [T](src: *const T) => is_aligned_and_not_null(src) + ( + addr: *const () = src as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); crate::intrinsics::read_via_copy(src) } @@ -1411,9 +1424,13 @@ pub const unsafe fn write(dst: *mut T, src: T) { // `dst` cannot overlap `src` because the caller has mutable access // to `dst` while `src` is owned by this function. unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) assert_unsafe_precondition!( "ptr::write requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::write_via_move(dst, src) } @@ -1581,7 +1598,10 @@ pub unsafe fn read_volatile(src: *const T) -> T { unsafe { assert_unsafe_precondition!( "ptr::read_volatile requires that the pointer argument is aligned and non-null", - [T](src: *const T) => is_aligned_and_not_null(src) + ( + addr: *const () = src as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::volatile_load(src) } @@ -1656,7 +1676,10 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { unsafe { assert_unsafe_precondition!( "ptr::write_volatile requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::volatile_store(dst, src); } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d18082c3048f1..d6266ba8da52e 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -218,7 +218,10 @@ impl NonNull { pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: the caller must guarantee that `ptr` is non-null. unsafe { - assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null()); + assert_unsafe_precondition!( + "NonNull::new_unchecked requires that the pointer is non-null", + (ptr: *mut () = ptr as *mut ()) => !ptr.is_null() + ); NonNull { pointer: ptr as _ } } } diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 9cdf9b68afb72..571abc3e99907 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -4,6 +4,7 @@ use crate::array; use crate::intrinsics::{ assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size, }; +use crate::mem::{align_of, size_of}; use crate::ops::Range; use crate::ptr; @@ -96,8 +97,14 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] unsafe { assert_unsafe_precondition!( "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", - [T](data: *const T, len: usize) => is_aligned_and_not_null(data) - && is_valid_allocation_size::(len) + ( + data: *mut () = data as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + len: usize = len, + ) => + is_aligned_and_not_null(data, align) + && is_valid_allocation_size(size, len) ); &*ptr::slice_from_raw_parts(data, len) } @@ -143,8 +150,14 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m unsafe { assert_unsafe_precondition!( "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", - [T](data: *mut T, len: usize) => is_aligned_and_not_null(data) - && is_valid_allocation_size::(len) + ( + data: *mut () = data as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + len: usize = len, + ) => + is_aligned_and_not_null(data, align) + && is_valid_allocation_size(size, len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) } From b0ea682a2cad2c49595c95dcb7e7608d090484f1 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:29:07 -0500 Subject: [PATCH 666/676] Remove a now-obviated debug_assert! --- library/core/src/option.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c94e7d73a2ae6..ab005228984e0 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1033,7 +1033,6 @@ impl Option { #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] pub const unsafe fn unwrap_unchecked(self) -> T { - debug_assert!(self.is_some()); match self { Some(val) => val, // SAFETY: the safety contract must be upheld by the caller. From 88d6e9f868d7bd21aa2b6c641f8743fe7e53e67b Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:29:33 -0500 Subject: [PATCH 667/676] Reduce use of NonNull::new_unchecked in library/ --- library/alloc/src/raw_vec.rs | 13 +++++++------ library/alloc/src/vec/into_iter.rs | 2 +- library/alloc/src/vec/mod.rs | 6 +++--- library/core/src/ptr/non_null.rs | 10 ++++------ library/core/src/ptr/unique.rs | 2 +- library/core/src/slice/iter.rs | 15 ++++++++------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 94e6924f41a75..49f5f53f9b30a 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -207,11 +207,7 @@ impl RawVec { // Allocators currently return a `NonNull<[u8]>` whose length // matches the size requested. If that ever changes, the capacity // here should change to `ptr.len() / mem::size_of::()`. - Self { - ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, - cap: unsafe { Cap(capacity) }, - alloc, - } + Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc } } } @@ -239,6 +235,11 @@ impl RawVec { self.ptr.as_ptr() } + #[inline] + pub fn non_null(&self) -> NonNull { + NonNull::from(self.ptr) + } + /// Gets the capacity of the allocation. /// /// This will always be `usize::MAX` if `T` is zero-sized. @@ -398,7 +399,7 @@ impl RawVec { // Allocators currently return a `NonNull<[u8]>` whose length matches // the size requested. If that ever changes, the capacity here should // change to `ptr.len() / mem::size_of::()`. - self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }; + self.ptr = Unique::from(ptr.cast()); self.cap = unsafe { Cap(cap) }; } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 654ce09afcd30..7800560da94f9 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -136,7 +136,7 @@ impl IntoIter { // struct and then overwriting &mut self. // this creates less assembly self.cap = 0; - self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; + self.buf = RawVec::NEW.non_null(); self.ptr = self.buf; self.end = self.buf.as_ptr(); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b3e5ecc924071..08e3cdedc666b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2861,16 +2861,16 @@ impl IntoIterator for Vec { #[inline] fn into_iter(self) -> Self::IntoIter { unsafe { - let mut me = ManuallyDrop::new(self); + let me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); - let begin = me.as_mut_ptr(); + let buf = me.buf.non_null(); + let begin = buf.as_ptr(); let end = if T::IS_ZST { begin.wrapping_byte_add(me.len()) } else { begin.add(me.len()) as *const T }; let cap = me.buf.capacity(); - let buf = NonNull::new_unchecked(begin); IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end } } } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d6266ba8da52e..575af96fc982f 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -473,7 +473,7 @@ impl NonNull { #[inline] pub const fn cast(self) -> NonNull { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null - unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } + unsafe { NonNull { pointer: self.as_ptr() as *mut U } } } /// Calculates the offset from a pointer. @@ -1828,9 +1828,8 @@ impl hash::Hash for NonNull { impl From> for NonNull { #[inline] fn from(unique: Unique) -> Self { - // SAFETY: A Unique pointer cannot be null, so the conditions for - // new_unchecked() are respected. - unsafe { NonNull::new_unchecked(unique.as_ptr()) } + // SAFETY: A Unique pointer cannot be null. + unsafe { NonNull { pointer: unique.as_ptr() } } } } @@ -1853,8 +1852,7 @@ impl From<&T> for NonNull { /// This conversion is safe and infallible since references cannot be null. #[inline] fn from(reference: &T) -> Self { - // SAFETY: A reference cannot be null, so the conditions for - // new_unchecked() are respected. + // SAFETY: A reference cannot be null. unsafe { NonNull { pointer: reference as *const T } } } } diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 067f1541e31ae..2d878836b1627 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -138,7 +138,7 @@ impl Unique { pub const fn cast(self) -> Unique { // FIXME(const-hack): replace with `From` // SAFETY: is `NonNull` - unsafe { Unique::new_unchecked(self.pointer.cast().as_ptr()) } + Unique { pointer: self.pointer.cast(), _marker: PhantomData } } } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 2d4c7e78aea17..1ca4ecbfba9e9 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -87,12 +87,13 @@ unsafe impl Send for Iter<'_, T> {} impl<'a, T> Iter<'a, T> { #[inline] pub(super) fn new(slice: &'a [T]) -> Self { - let ptr = slice.as_ptr(); + let len = slice.len(); + let ptr: NonNull = NonNull::from(slice).cast(); // SAFETY: Similar to `IterMut::new`. unsafe { - let end_or_len = if T::IS_ZST { invalid(slice.len()) } else { ptr.add(slice.len()) }; + let end_or_len = if T::IS_ZST { invalid(len) } else { ptr.as_ptr().add(len) }; - Self { ptr: NonNull::new_unchecked(ptr as *mut T), end_or_len, _marker: PhantomData } + Self { ptr, end_or_len, _marker: PhantomData } } } @@ -208,7 +209,8 @@ unsafe impl Send for IterMut<'_, T> {} impl<'a, T> IterMut<'a, T> { #[inline] pub(super) fn new(slice: &'a mut [T]) -> Self { - let ptr = slice.as_mut_ptr(); + let len = slice.len(); + let ptr: NonNull = NonNull::from(slice).cast(); // SAFETY: There are several things here: // // `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid @@ -226,10 +228,9 @@ impl<'a, T> IterMut<'a, T> { // See the `next_unchecked!` and `is_empty!` macros as well as the // `post_inc_start` method for more information. unsafe { - let end_or_len = - if T::IS_ZST { invalid_mut(slice.len()) } else { ptr.add(slice.len()) }; + let end_or_len = if T::IS_ZST { invalid_mut(len) } else { ptr.as_ptr().add(len) }; - Self { ptr: NonNull::new_unchecked(ptr), end_or_len, _marker: PhantomData } + Self { ptr, end_or_len, _marker: PhantomData } } } From ad511ef92ed5454182c1c6b3afe0846d654af009 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 8 Feb 2024 17:33:04 +0000 Subject: [PATCH 668/676] Avoid ICE in drop recursion check in case of invalid drop impls --- compiler/rustc_middle/src/ty/sty.rs | 1 + compiler/rustc_mir_build/src/lints.rs | 11 +++++------ tests/ui/drop/recursion-check-on-erroneous-impl.rs | 11 +++++++++++ .../ui/drop/recursion-check-on-erroneous-impl.stderr | 11 +++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 tests/ui/drop/recursion-check-on-erroneous-impl.rs create mode 100644 tests/ui/drop/recursion-check-on-erroneous-impl.stderr diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 927924452f913..55801d8074a3e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1312,6 +1312,7 @@ impl<'tcx> PolyFnSig<'tcx> { self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) } #[inline] + #[track_caller] pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 337493d15deca..508936be29d71 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -72,15 +72,14 @@ pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id)) && let Some(drop_trait) = tcx.lang_items().drop_trait() && drop_trait == trait_ref.instantiate_identity().def_id + // avoid erroneous `Drop` impls from causing ICEs below + && let sig = tcx.fn_sig(def_id).instantiate_identity() + && sig.inputs().skip_binder().len() == 1 { // It was. Now figure out for what type `Drop` is implemented and then // check for recursion. - if let ty::Ref(_, dropped_ty, _) = tcx - .liberate_late_bound_regions( - def_id.to_def_id(), - tcx.fn_sig(def_id).instantiate_identity().input(0), - ) - .kind() + if let ty::Ref(_, dropped_ty, _) = + tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind() { check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty }); } diff --git a/tests/ui/drop/recursion-check-on-erroneous-impl.rs b/tests/ui/drop/recursion-check-on-erroneous-impl.rs new file mode 100644 index 0000000000000..733c8b0b08590 --- /dev/null +++ b/tests/ui/drop/recursion-check-on-erroneous-impl.rs @@ -0,0 +1,11 @@ +// can't use build-fail, because this also fails check-fail, but +// the ICE from #120787 only reproduces on build-fail. +// compile-flags: --emit=mir + +struct PrintOnDrop<'a>(&'a str); + +impl Drop for PrintOnDrop<'_> { + fn drop() {} //~ ERROR method `drop` has a `&mut self` declaration in the trait +} + +fn main() {} diff --git a/tests/ui/drop/recursion-check-on-erroneous-impl.stderr b/tests/ui/drop/recursion-check-on-erroneous-impl.stderr new file mode 100644 index 0000000000000..831adb88cefac --- /dev/null +++ b/tests/ui/drop/recursion-check-on-erroneous-impl.stderr @@ -0,0 +1,11 @@ +error[E0186]: method `drop` has a `&mut self` declaration in the trait, but not in the impl + --> $DIR/recursion-check-on-erroneous-impl.rs:8:5 + | +LL | fn drop() {} + | ^^^^^^^^^ expected `&mut self` in impl + | + = note: `drop` from trait: `fn(&mut Self)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0186`. From d70d3204b7e669ff8046bfe55999a36a39896c08 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 8 Feb 2024 20:40:55 +0100 Subject: [PATCH 669/676] Use `transmute_unchecked` in `NonZero::new`. --- library/core/src/num/nonzero.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 193f2fa8731af..bf676cb22489e 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -8,7 +8,6 @@ use crate::intrinsics; use crate::marker::StructuralEq; use crate::marker::StructuralPartialEq; use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem}; -use crate::ptr; use crate::str::FromStr; use super::from_str_radix; @@ -91,13 +90,12 @@ where /// Creates a non-zero if the given value is not zero. #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] - #[rustc_allow_const_fn_unstable(const_refs_to_cell)] #[must_use] #[inline] pub const fn new(n: T) -> Option { // SAFETY: Memory layout optimization guarantees that `Option>` has // the same layout and size as `T`, with `0` representing `None`. - unsafe { ptr::read(ptr::addr_of!(n).cast()) } + unsafe { intrinsics::transmute_unchecked(n) } } /// Creates a non-zero without checking whether the value is non-zero. From 698a3c7adeed1213e1c3af73158566a85795a3c2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 8 Feb 2024 19:47:02 +0000 Subject: [PATCH 670/676] Don't ICE in ByMoveBody when coroutine is tainted --- compiler/rustc_mir_build/src/build/mod.rs | 36 +++++++++++++------ .../src/coroutine/by_move_body.rs | 7 ++-- .../async-closures/tainted-body.rs | 13 +++++++ .../async-closures/tainted-body.stderr | 9 +++++ 4 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 tests/ui/async-await/async-closures/tainted-body.rs create mode 100644 tests/ui/async-await/async-closures/tainted-body.stderr diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index c24f2e9f53a84..2b1a9fef360c0 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -675,16 +675,32 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - ))), ) } - ty::CoroutineClosure(did, _args) => { - // FIXME(async_closures): Recover the proper error signature - let inputs = tcx - .closure_user_provided_sig(did.expect_local()) - .value - .skip_binder() - .inputs(); - - let err = Ty::new_error(tcx, guar); - (inputs.iter().map(|_| err).collect(), err, None) + ty::CoroutineClosure(did, args) => { + let args = args.as_coroutine_closure(); + let sig = tcx.liberate_late_bound_regions( + def_id.to_def_id(), + args.coroutine_closure_sig(), + ); + let self_ty = match args.kind() { + ty::ClosureKind::Fn => { + Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty) + } + ty::ClosureKind::FnMut => { + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty) + } + ty::ClosureKind::FnOnce => closure_ty, + }; + ( + [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()).collect(), + sig.to_coroutine( + tcx, + args.parent_args(), + args.kind_ty(), + tcx.coroutine_for_closure(*did), + Ty::new_error(tcx, guar), + ), + None, + ) } ty::Error(_) => (vec![closure_ty, closure_ty], closure_ty, None), kind => { diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index fcd4715b9e88c..e40f4520671bb 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{self, dump_mir, MirPass}; -use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt}; +use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt}; use rustc_target::abi::FieldIdx; pub struct ByMoveBody; @@ -23,7 +23,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { return; }; let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!() }; + if coroutine_ty.references_error() { + return; + } + let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; let coroutine_kind = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(); if coroutine_kind == ty::ClosureKind::FnOnce { diff --git a/tests/ui/async-await/async-closures/tainted-body.rs b/tests/ui/async-await/async-closures/tainted-body.rs new file mode 100644 index 0000000000000..62c28e7e58576 --- /dev/null +++ b/tests/ui/async-await/async-closures/tainted-body.rs @@ -0,0 +1,13 @@ +// edition:2021 + +#![feature(async_closure)] + +// Don't ICE in ByMove shim builder when MIR body is tainted by writeback errors + +fn main() { + let _ = async || { + used_fn(); + //~^ ERROR cannot find function `used_fn` in this scope + 0 + }; +} diff --git a/tests/ui/async-await/async-closures/tainted-body.stderr b/tests/ui/async-await/async-closures/tainted-body.stderr new file mode 100644 index 0000000000000..b06a896b81f52 --- /dev/null +++ b/tests/ui/async-await/async-closures/tainted-body.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `used_fn` in this scope + --> $DIR/tainted-body.rs:9:9 + | +LL | used_fn(); + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. From e32c1ddc5274636c03697f180224f4fa6721f200 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 9 Feb 2024 00:40:43 +0000 Subject: [PATCH 671/676] Don't ice in validation when error body is created --- compiler/rustc_const_eval/src/transform/validate.rs | 2 ++ tests/ui/mir/validate/error-body.rs | 9 +++++++++ tests/ui/mir/validate/error-body.stderr | 9 +++++++++ 3 files changed, 20 insertions(+) create mode 100644 tests/ui/mir/validate/error-body.rs create mode 100644 tests/ui/mir/validate/error-body.stderr diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index c4542aaa7b2fb..3b7b502d3d08a 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -60,6 +60,8 @@ impl<'tcx> MirPass<'tcx> for Validator { ty::Closure(..) => Abi::RustCall, ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + // No need to do MIR validation on error bodies + ty::Error(_) => return, _ => { span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase) } diff --git a/tests/ui/mir/validate/error-body.rs b/tests/ui/mir/validate/error-body.rs new file mode 100644 index 0000000000000..5b2fbb0b04699 --- /dev/null +++ b/tests/ui/mir/validate/error-body.rs @@ -0,0 +1,9 @@ +// compile-flags: -Zvalidate-mir + +fn _test() { + let x = || 45; + missing(); + //~^ ERROR cannot find function `missing` in this scope +} + +fn main() {} diff --git a/tests/ui/mir/validate/error-body.stderr b/tests/ui/mir/validate/error-body.stderr new file mode 100644 index 0000000000000..1dfeaf0b7e2cb --- /dev/null +++ b/tests/ui/mir/validate/error-body.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `missing` in this scope + --> $DIR/error-body.rs:5:5 + | +LL | missing(); + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. From 9e1b2d909bec461d334b412bdbc0d0f8ba6c17ed Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:30:11 -0500 Subject: [PATCH 672/676] Add new ui tests --- src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/precondition-checks/misaligned-slice.rs | 11 +++++++++++ tests/ui/precondition-checks/null-slice.rs | 11 +++++++++++ .../out-of-bounds-get-unchecked.rs | 12 ++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests/ui/precondition-checks/misaligned-slice.rs create mode 100644 tests/ui/precondition-checks/null-slice.rs create mode 100644 tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 4a44c40debd22..d5df05bacd93f 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1819; -const ROOT_ENTRY_LIMIT: usize = 871; +const ROOT_ENTRY_LIMIT: usize = 872; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/precondition-checks/misaligned-slice.rs b/tests/ui/precondition-checks/misaligned-slice.rs new file mode 100644 index 0000000000000..c961c80035232 --- /dev/null +++ b/tests/ui/precondition-checks/misaligned-slice.rs @@ -0,0 +1,11 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let _s: &[u64] = std::slice::from_raw_parts(1usize as *const u64, 0); + } +} diff --git a/tests/ui/precondition-checks/null-slice.rs b/tests/ui/precondition-checks/null-slice.rs new file mode 100644 index 0000000000000..1e67e7f5fb1d0 --- /dev/null +++ b/tests/ui/precondition-checks/null-slice.rs @@ -0,0 +1,11 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0); + } +} diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs new file mode 100644 index 0000000000000..1366ba28f1c9e --- /dev/null +++ b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs @@ -0,0 +1,12 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: hint::assert_unchecked +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let sli: &[u8] = &[0]; + sli.get_unchecked(1); + } +} From 611c3cb56109593824f3570720d8404b591724cc Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:30:39 -0500 Subject: [PATCH 673/676] Bless/fix tests --- tests/assembly/is_aligned.rs | 4 +- ...n.DataflowConstProp.32bit.panic-abort.diff | 60 ++--- ....DataflowConstProp.32bit.panic-unwind.diff | 68 +++-- ...n.DataflowConstProp.64bit.panic-abort.diff | 60 ++--- ....DataflowConstProp.64bit.panic-unwind.diff | 68 +++-- ...oxed_slice.main.GVN.32bit.panic-abort.diff | 63 +++-- ...xed_slice.main.GVN.32bit.panic-unwind.diff | 71 +++-- ...oxed_slice.main.GVN.64bit.panic-abort.diff | 63 +++-- ...xed_slice.main.GVN.64bit.panic-unwind.diff | 71 +++-- tests/mir-opt/inline/unwrap_unchecked.rs | 2 +- ...d.unwrap_unchecked.Inline.panic-abort.diff | 39 +-- ....unwrap_unchecked.Inline.panic-unwind.diff | 51 ++-- ...unchecked.PreCodegen.after.panic-abort.mir | 34 +-- ...nchecked.PreCodegen.after.panic-unwind.mir | 34 +-- ...witch_targets.ub_if_b.PreCodegen.after.mir | 22 +- ..._replace.PreCodegen.after.panic-abort.mir} | 0 ..._replace.PreCodegen.after.panic-unwind.mir | 16 ++ ...m_replace.mem_replace.PreCodegen.after.mir | 66 ----- ...m_replace.PreCodegen.after.panic-abort.mir | 33 +++ ..._replace.PreCodegen.after.panic-unwind.mir | 33 +++ tests/mir-opt/pre-codegen/mem_replace.rs | 3 +- ...ated_loop.PreCodegen.after.panic-abort.mir | 240 +++++++++-------- ...ted_loop.PreCodegen.after.panic-unwind.mir | 240 +++++++++-------- ...ward_loop.PreCodegen.after.panic-abort.mir | 216 ++++++++-------- ...ard_loop.PreCodegen.after.panic-unwind.mir | 216 ++++++++-------- ...erse_loop.PreCodegen.after.panic-abort.mir | 244 +++++++++--------- ...rse_loop.PreCodegen.after.panic-unwind.mir | 244 +++++++++--------- tests/ui/hygiene/panic-location.run.stderr | 2 +- 28 files changed, 1113 insertions(+), 1150 deletions(-) rename tests/mir-opt/pre-codegen/{mem_replace.manual_replace.PreCodegen.after.mir => mem_replace.manual_replace.PreCodegen.after.panic-abort.mir} (100%) create mode 100644 tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir delete mode 100644 tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir create mode 100644 tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir create mode 100644 tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir diff --git a/tests/assembly/is_aligned.rs b/tests/assembly/is_aligned.rs index d152d200adfd7..c4a7823ce1ad4 100644 --- a/tests/assembly/is_aligned.rs +++ b/tests/assembly/is_aligned.rs @@ -2,8 +2,8 @@ // only-x86_64 // ignore-sgx // revisions: opt-speed opt-size -// [opt-speed] compile-flags: -Copt-level=1 -// [opt-size] compile-flags: -Copt-level=s +// [opt-speed] compile-flags: -Copt-level=2 -Cdebug-assertions=no +// [opt-size] compile-flags: -Copt-level=s -Cdebug-assertions=no #![crate_type="rlib"] #![feature(core_intrinsics)] diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index ffbd97bb5452f..94cfb4e63fc22 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,30 +56,41 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 7b6dcf1972b2e..ee85287882be9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,34 +56,45 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index ffbd97bb5452f..94cfb4e63fc22 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,30 +56,41 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 7b6dcf1972b2e..ee85287882be9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,34 +56,45 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index df68ce496fd8c..4df38d6e61b7e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,31 +58,43 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index e16ea22091ee2..6aac30bcd17fb 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,35 +58,47 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index df68ce496fd8c..4df38d6e61b7e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,31 +58,43 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index e16ea22091ee2..6aac30bcd17fb 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,35 +58,47 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.rs b/tests/mir-opt/inline/unwrap_unchecked.rs index be133706e5c22..1adf2224d976a 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.rs +++ b/tests/mir-opt/inline/unwrap_unchecked.rs @@ -2,7 +2,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // ignore-debug: the debug assertions prevent the inlining we are testing for -// compile-flags: -Zmir-opt-level=2 -Zinline-mir +// compile-flags: -Zmir-opt-level=2 -Zinline-mir -Cdebug-assertions=no // EMIT_MIR unwrap_unchecked.unwrap_unchecked.Inline.diff // EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index 2a36ad9230e4b..9358a64b4fabe 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -7,41 +7,44 @@ let mut _2: std::option::Option; + scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { + debug self => _2; -+ let mut _3: &std::option::Option; -+ let mut _4: isize; -+ let mut _5: bool; ++ let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 { -+ scope 5 (inlined unreachable_unchecked) { -+ scope 6 { -+ scope 7 (inlined unreachable_unchecked::runtime) { -+ } ++ scope 4 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 5 { + } + } + } -+ scope 4 (inlined Option::::is_some) { -+ debug self => _3; -+ } + } bb0: { StorageLive(_2); _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable]; -- } -- -- bb1: { + StorageLive(_3); -+ StorageLive(_4); + StorageLive(_5); -+ _4 = discriminant(_2); -+ _5 = Eq(_4, const 1_isize); -+ assume(move _5); ++ _3 = discriminant(_2); ++ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { ++ StorageLive(_4); ++ _4 = cfg!(debug_assertions); ++ assume(_4); ++ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; ++ } ++ ++ bb2: { ++ unreachable; ++ } ++ ++ bb3: { + _0 = move ((_2 as Some).0: T); + StorageDead(_5); -+ StorageDead(_4); + StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index 14c8c671d3fe2..ac33c126155ca 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -7,48 +7,51 @@ let mut _2: std::option::Option; + scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { + debug self => _2; -+ let mut _3: &std::option::Option; -+ let mut _4: isize; -+ let mut _5: bool; ++ let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 { -+ scope 5 (inlined unreachable_unchecked) { -+ scope 6 { -+ scope 7 (inlined unreachable_unchecked::runtime) { -+ } ++ scope 4 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 5 { + } + } + } -+ scope 4 (inlined Option::::is_some) { -+ debug self => _3; -+ } + } bb0: { StorageLive(_2); _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2]; -- } -- -- bb1: { + StorageLive(_3); -+ StorageLive(_4); + StorageLive(_5); -+ _4 = discriminant(_2); -+ _5 = Eq(_4, const 1_isize); -+ assume(move _5); ++ _3 = discriminant(_2); ++ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { +- StorageDead(_2); +- return; ++ StorageLive(_4); ++ _4 = cfg!(debug_assertions); ++ assume(_4); ++ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; + } + +- bb2 (cleanup): { +- resume; ++ bb2: { ++ unreachable; ++ } ++ ++ bb3: { + _0 = move ((_2 as Some).0: T); + StorageDead(_5); -+ StorageDead(_4); + StorageDead(_3); - StorageDead(_2); - return; -- } -- -- bb2 (cleanup): { -- resume; ++ StorageDead(_2); ++ return; } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index d6a608476df9c..8ec65935c6612 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option) -> T { scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { debug self => _1; let mut _2: isize; - let mut _3: bool; - let mut _4: &std::option::Option; scope 2 { debug val => _0; } scope 3 { - scope 5 (inlined unreachable_unchecked) { - scope 6 { - scope 7 (inlined unreachable_unchecked::runtime) { - } + scope 4 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); + scope 5 { } } } - scope 4 (inlined Option::::is_some) { - debug self => _4; - } } bb0: { - StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); - _3 = Eq(_2, const 1_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb2: { _0 = ((_1 as Some).0: T); - StorageDead(_3); StorageDead(_2); - StorageDead(_4); return; } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index d6a608476df9c..8ec65935c6612 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option) -> T { scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { debug self => _1; let mut _2: isize; - let mut _3: bool; - let mut _4: &std::option::Option; scope 2 { debug val => _0; } scope 3 { - scope 5 (inlined unreachable_unchecked) { - scope 6 { - scope 7 (inlined unreachable_unchecked::runtime) { - } + scope 4 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); + scope 5 { } } } - scope 4 (inlined Option::::is_some) { - debug self => _4; - } } bb0: { - StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); - _3 = Eq(_2, const 1_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb2: { _0 = ((_1 as Some).0: T); - StorageDead(_3); StorageDead(_2); - StorageDead(_4); return; } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir index 0114309dbb58e..7c038b0ee88e7 100644 --- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir @@ -4,19 +4,31 @@ fn ub_if_b(_1: Thing) -> Thing { debug t => _1; let mut _0: Thing; let mut _2: isize; - let mut _3: bool; scope 1 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); scope 2 { - scope 3 (inlined unreachable_unchecked::runtime) { - } } } bb0: { _2 = discriminant(_1); - _3 = Eq(_2, const 0_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { _0 = move _1; return; } + + bb2: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir similarity index 100% rename from tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir rename to tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..3ca24e152a4e0 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,16 @@ +// MIR for `manual_replace` after PreCodegen + +fn manual_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 { + debug temp => _0; + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir deleted file mode 100644 index f0cb4ca31fecc..0000000000000 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir +++ /dev/null @@ -1,66 +0,0 @@ -// MIR for `mem_replace` after PreCodegen - -fn mem_replace(_1: &mut u32, _2: u32) -> u32 { - debug r => _1; - debug v => _2; - let mut _0: u32; - scope 1 (inlined std::mem::replace::) { - debug dest => _1; - debug src => _2; - scope 2 { - scope 3 { - debug result => _0; - scope 16 (inlined std::ptr::write::) { - debug dst => _1; - debug src => _2; - scope 17 { - } - } - } - scope 4 (inlined std::ptr::read::) { - debug src => _1; - let mut _3: *const u32; - scope 5 { - scope 6 (inlined std::ptr::read::runtime::) { - debug src => _3; - scope 7 (inlined intrinsics::is_aligned_and_not_null::) { - debug ptr => _3; - scope 8 (inlined std::ptr::const_ptr::::is_null) { - debug self => _3; - let mut _4: *const u8; - scope 9 { - scope 10 (inlined std::ptr::const_ptr::::is_null::runtime_impl) { - debug ptr => _4; - scope 11 (inlined std::ptr::const_ptr::::addr) { - debug self => _4; - scope 12 { - scope 13 (inlined std::ptr::const_ptr::::cast::<()>) { - debug self => _4; - } - } - } - } - } - } - scope 14 (inlined std::ptr::const_ptr::::is_aligned) { - debug self => _3; - scope 15 (inlined align_of::) { - } - } - } - } - } - } - } - } - - bb0: { - StorageLive(_3); - StorageLive(_4); - _0 = (*_1); - StorageDead(_4); - StorageDead(_3); - (*_1) = _2; - return; - } -} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir new file mode 100644 index 0000000000000..26919dd98dd27 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir @@ -0,0 +1,33 @@ +// MIR for `mem_replace` after PreCodegen + +fn mem_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 (inlined std::mem::replace::) { + debug dest => _1; + debug src => _2; + scope 2 { + scope 3 { + debug result => _0; + scope 6 (inlined std::ptr::write::) { + debug dst => _1; + debug src => _2; + scope 7 { + } + } + } + scope 4 (inlined std::ptr::read::) { + debug src => _1; + scope 5 { + } + } + } + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..26919dd98dd27 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,33 @@ +// MIR for `mem_replace` after PreCodegen + +fn mem_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 (inlined std::mem::replace::) { + debug dest => _1; + debug src => _2; + scope 2 { + scope 3 { + debug result => _0; + scope 6 (inlined std::ptr::write::) { + debug dst => _1; + debug src => _2; + scope 7 { + } + } + } + scope 4 (inlined std::ptr::read::) { + debug src => _1; + scope 5 { + } + } + } + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs index 18c4653d4c6ea..551afea3ba5a8 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.rs +++ b/tests/mir-opt/pre-codegen/mem_replace.rs @@ -1,7 +1,8 @@ // skip-filecheck -// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 +// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir // only-64bit // ignore-debug the standard library debug assertions leak into this test +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 26b2663fa3580..4906c86f8ed97 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Enumerate>; - let mut _15: std::iter::Enumerate>; - let mut _16: &mut std::iter::Enumerate>; - let mut _17: std::option::Option<(usize, &T)>; - let mut _18: isize; - let mut _21: &impl Fn(usize, &T); - let mut _22: (usize, &T); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Enumerate>; + let mut _17: std::iter::Enumerate>; + let mut _18: &mut std::iter::Enumerate>; + let mut _19: std::option::Option<(usize, &T)>; + let mut _20: isize; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _17; + let _21: usize; + let _22: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _21; + debug x => _22; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::enumerate) { - debug self => _13; - scope 23 (inlined Enumerate::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::enumerate) { + debug self => _15; + scope 20 (inlined Enumerate::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Enumerate::> { iter: _13, count: const 0_usize }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Enumerate::> { iter: _15, count: const 0_usize }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_17); - StorageLive(_16); - _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind unreachable]; + StorageLive(_19); + StorageLive(_18); + _18 = &mut _17; + _19 = > as Iterator>::next(move _18) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_18); + _20 = discriminant(_19); + switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_19); StorageDead(_17); - StorageDead(_15); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _21 = (((_19 as Some).0: (usize, &T)).0: usize); + _22 = (((_19 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_21, _22); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_17); + StorageDead(_24); + StorageDead(_23); + StorageDead(_19); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index a055612bd5feb..25a5ecdc6c360 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Enumerate>; - let mut _15: std::iter::Enumerate>; - let mut _16: &mut std::iter::Enumerate>; - let mut _17: std::option::Option<(usize, &T)>; - let mut _18: isize; - let mut _21: &impl Fn(usize, &T); - let mut _22: (usize, &T); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Enumerate>; + let mut _17: std::iter::Enumerate>; + let mut _18: &mut std::iter::Enumerate>; + let mut _19: std::option::Option<(usize, &T)>; + let mut _20: isize; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _17; + let _21: usize; + let _22: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _21; + debug x => _22; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::enumerate) { - debug self => _13; - scope 23 (inlined Enumerate::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::enumerate) { + debug self => _15; + scope 20 (inlined Enumerate::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Enumerate::> { iter: _13, count: const 0_usize }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Enumerate::> { iter: _15, count: const 0_usize }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_17); - StorageLive(_16); - _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind: bb11]; + StorageLive(_19); + StorageLive(_18); + _18 = &mut _17; + _19 = > as Iterator>::next(move _18) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_18); + _20 = discriminant(_19); + switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_19); StorageDead(_17); - StorageDead(_15); drop(_2) -> [return: bb7, unwind continue]; } @@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _21 = (((_19 as Some).0: (usize, &T)).0: usize); + _22 = (((_19 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_21, _22); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_17); + StorageDead(_24); + StorageDead(_23); + StorageDead(_19); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 471491108e0b6..133d6f53fce11 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::slice::Iter<'_, T>; - let mut _15: &mut std::slice::Iter<'_, T>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::slice::Iter<'_, T>; + let mut _17: &mut std::slice::Iter<'_, T>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _16; + let _20: &T; scope 2 { - debug x => _18; + debug x => _20; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _22: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _22; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _22; - let mut _23: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _23; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _23; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _23; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as IntoIterator>::into_iter) { - debug self => _13; + scope 19 (inlined as IntoIterator>::into_iter) { + debug self => _15; } bb0: { - StorageLive(_4); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_22); - StorageLive(_23); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_23); - StorageDead(_22); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); StorageLive(_14); _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); + StorageDead(_13); + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + StorageLive(_16); + _16 = _15; goto -> bb4; } bb4: { - StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; + StorageLive(_18); + StorageLive(_17); + _17 = &mut _16; + _18 = as Iterator>::next(move _17) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_18); StorageDead(_16); - StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); - StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; + _20 = ((_18 as Some).0: &T); + StorageLive(_21); + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_20); - StorageDead(_19); - StorageDead(_16); + StorageDead(_22); + StorageDead(_21); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index bbf38aba91f08..4e74253e54172 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::slice::Iter<'_, T>; - let mut _15: &mut std::slice::Iter<'_, T>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::slice::Iter<'_, T>; + let mut _17: &mut std::slice::Iter<'_, T>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _16; + let _20: &T; scope 2 { - debug x => _18; + debug x => _20; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _22: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _22; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _22; - let mut _23: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _23; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _23; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _23; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as IntoIterator>::into_iter) { - debug self => _13; + scope 19 (inlined as IntoIterator>::into_iter) { + debug self => _15; } bb0: { - StorageLive(_4); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_22); - StorageLive(_23); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_23); - StorageDead(_22); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); StorageLive(_14); _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); + StorageDead(_13); + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + StorageLive(_16); + _16 = _15; goto -> bb4; } bb4: { - StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + StorageLive(_18); + StorageLive(_17); + _17 = &mut _16; + _18 = as Iterator>::next(move _17) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_18); StorageDead(_16); - StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); - StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _20 = ((_18 as Some).0: &T); + StorageLive(_21); + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_20); - StorageDead(_19); - StorageDead(_16); + StorageDead(_22); + StorageDead(_21); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index f9c8ab4db60b7..639e1a51430db 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Rev>; - let mut _15: std::iter::Rev>; - let mut _16: &mut std::iter::Rev>; - let mut _18: std::option::Option<&T>; - let mut _19: isize; - let mut _21: &impl Fn(&T); - let mut _22: (&T,); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Rev>; + let mut _17: std::iter::Rev>; + let mut _18: &mut std::iter::Rev>; + let mut _20: std::option::Option<&T>; + let mut _21: isize; + let mut _23: &impl Fn(&T); + let mut _24: (&T,); + let _25: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _17; + let _22: &T; scope 2 { - debug x => _20; + debug x => _22; } - scope 25 (inlined > as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + scope 22 (inlined > as Iterator>::next) { + debug self => _18; + let mut _19: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::rev) { - debug self => _13; - scope 23 (inlined Rev::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::rev) { + debug self => _15; + scope 20 (inlined Rev::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Rev::> { iter: _13 }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Rev::> { iter: _15 }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; - StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable]; + StorageLive(_20); + _18 = &mut _17; + StorageLive(_19); + _19 = &mut (_17.0: std::slice::Iter<'_, T>); + _20 = as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_19); + _21 = discriminant(_20); + switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_20); + StorageDead(_17); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _22 = ((_20 as Some).0: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_22,); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_18); + StorageDead(_24); + StorageDead(_23); + StorageDead(_20); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 65f423ac326be..2237fd7dbd12c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Rev>; - let mut _15: std::iter::Rev>; - let mut _16: &mut std::iter::Rev>; - let mut _18: std::option::Option<&T>; - let mut _19: isize; - let mut _21: &impl Fn(&T); - let mut _22: (&T,); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Rev>; + let mut _17: std::iter::Rev>; + let mut _18: &mut std::iter::Rev>; + let mut _20: std::option::Option<&T>; + let mut _21: isize; + let mut _23: &impl Fn(&T); + let mut _24: (&T,); + let _25: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _17; + let _22: &T; scope 2 { - debug x => _20; + debug x => _22; } - scope 25 (inlined > as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + scope 22 (inlined > as Iterator>::next) { + debug self => _18; + let mut _19: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::rev) { - debug self => _13; - scope 23 (inlined Rev::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::rev) { + debug self => _15; + scope 20 (inlined Rev::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Rev::> { iter: _13 }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Rev::> { iter: _15 }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; - StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11]; + StorageLive(_20); + _18 = &mut _17; + StorageLive(_19); + _19 = &mut (_17.0: std::slice::Iter<'_, T>); + _20 = as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_19); + _21 = discriminant(_20); + switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_20); + StorageDead(_17); drop(_2) -> [return: bb7, unwind continue]; } @@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _22 = ((_20 as Some).0: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_22,); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_18); + StorageDead(_24); + StorageDead(_23); + StorageDead(_20); goto -> bb4; } diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5824ef31211be..5c552411da7f3 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:570:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From dbf817bae1f25f0fa2fbb1e40ab74afc892d9a60 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 8 Feb 2024 11:11:13 -0500 Subject: [PATCH 674/676] Add and use Unique::as_non_null_ptr --- library/core/src/ptr/non_null.rs | 6 ++---- library/core/src/ptr/unique.rs | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 575af96fc982f..320cd5eb3b2ae 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1591,8 +1591,7 @@ impl NonNull<[T]> { #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] pub const fn as_non_null_ptr(self) -> NonNull { - // SAFETY: We know `self` is non-null. - unsafe { NonNull::new_unchecked(self.as_ptr().as_mut_ptr()) } + self.cast() } /// Returns a raw pointer to the slice's buffer. @@ -1828,8 +1827,7 @@ impl hash::Hash for NonNull { impl From> for NonNull { #[inline] fn from(unique: Unique) -> Self { - // SAFETY: A Unique pointer cannot be null. - unsafe { NonNull { pointer: unique.as_ptr() } } + unique.as_non_null_ptr() } } diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 2d878836b1627..b74d691e45427 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -106,6 +106,13 @@ impl Unique { self.pointer.as_ptr() } + /// Acquires the underlying `*mut` pointer. + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub const fn as_non_null_ptr(self) -> NonNull { + self.pointer + } + /// Dereferences the content. /// /// The resulting lifetime is bound to self so this behaves "as if" From 76197921079737fdd499e12016ac056674b5119f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 9 Feb 2024 06:42:50 +1100 Subject: [PATCH 675/676] Fix `ErrorGuaranteed` unsoundness with stash/steal. When you stash an error, the error count is incremented. You can then use the non-zero error count to get an `ErrorGuaranteed`. You can then steal the error, which decrements the error count. You can then cancel the error. Example code: ``` fn unsound(dcx: &DiagCtxt) -> ErrorGuaranteed { let sp = rustc_span::DUMMY_SP; let k = rustc_errors::StashKey::Cycle; dcx.struct_err("bogus").stash(sp, k); // increment error count on stash let guar = dcx.has_errors().unwrap(); // ErrorGuaranteed from error count > 0 let err = dcx.steal_diagnostic(sp, k).unwrap(); // decrement error count on steal err.cancel(); // cancel error guar // ErrorGuaranteed with no error emitted! } ``` This commit fixes the problem in the simplest way: by not counting stashed errors in `DiagCtxt::{err_count,has_errors}`. However, just doing this without any other changes leads to over 40 ui test failures. Mostly because of uninteresting extra errors (many saying "type annotations needed" when type inference fails), and in a few cases, due to delayed bugs causing ICEs when no normal errors are printed. To fix these, this commit adds `DiagCtxt::stashed_err_count`, and uses it in three places alongside `DiagCtxt::{has_errors,err_count}`. It's dodgy to rely on it, because unlike `DiagCtxt::err_count` it can go up and down. But it's needed to preserve existing behaviour, and at least the three places that need it are now obvious. --- compiler/rustc_errors/src/lib.rs | 45 +++++++++++++--------- compiler/rustc_hir_typeck/src/writeback.rs | 14 ++++--- compiler/rustc_infer/src/infer/at.rs | 1 + compiler/rustc_infer/src/infer/mod.rs | 43 ++++++++++++--------- compiler/rustc_interface/src/passes.rs | 4 ++ 5 files changed, 65 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ec5029e505f96..26ee2770d882e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -429,6 +429,10 @@ struct DiagCtxtInner { /// The number of non-lint errors that have been emitted, including duplicates. err_count: usize, + /// The number of stashed errors. Unlike the other counts, this can go up + /// and down, so it doesn't guarantee anything. + stashed_err_count: usize, + /// The error count shown to the user at the end. deduplicated_err_count: usize, /// The warning count shown to the user at the end. @@ -598,6 +602,7 @@ impl DiagCtxt { flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, lint_err_count: 0, err_count: 0, + stashed_err_count: 0, deduplicated_err_count: 0, deduplicated_warn_count: 0, has_printed: false, @@ -654,6 +659,7 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); inner.lint_err_count = 0; inner.err_count = 0; + inner.stashed_err_count = 0; inner.deduplicated_err_count = 0; inner.deduplicated_warn_count = 0; inner.has_printed = false; @@ -675,10 +681,8 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if diag.is_lint.is_some() { - inner.lint_err_count += 1; - } else { - inner.err_count += 1; + if diag.is_lint.is_none() { + inner.stashed_err_count += 1; } } @@ -694,10 +698,8 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if diag.is_lint.is_some() { - inner.lint_err_count -= 1; - } else { - inner.err_count -= 1; + if diag.is_lint.is_none() { + inner.stashed_err_count -= 1; } } Some(DiagnosticBuilder::new_diagnostic(self, diag)) @@ -922,13 +924,22 @@ impl DiagCtxt { self.struct_bug(msg).emit() } - /// This excludes lint errors and delayed bugs. + /// This excludes lint errors, delayed bugs, and stashed errors. #[inline] pub fn err_count(&self) -> usize { self.inner.borrow().err_count } - /// This excludes lint errors and delayed bugs. + /// This excludes normal errors, lint errors and delayed bugs. Unless + /// absolutely necessary, avoid using this. It's dubious because stashed + /// errors can later be cancelled, so the presence of a stashed error at + /// some point of time doesn't guarantee anything -- there are no + /// `ErrorGuaranteed`s here. + pub fn stashed_err_count(&self) -> usize { + self.inner.borrow().stashed_err_count + } + + /// This excludes lint errors, delayed bugs, and stashed errors. pub fn has_errors(&self) -> Option { self.inner.borrow().has_errors().then(|| { // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. @@ -937,8 +948,8 @@ impl DiagCtxt { }) } - /// This excludes delayed bugs. Unless absolutely necessary, prefer - /// `has_errors` to this method. + /// This excludes delayed bugs and stashed errors. Unless absolutely + /// necessary, prefer `has_errors` to this method. pub fn has_errors_or_lint_errors(&self) -> Option { let inner = self.inner.borrow(); let result = inner.has_errors() || inner.lint_err_count > 0; @@ -949,8 +960,8 @@ impl DiagCtxt { }) } - /// Unless absolutely necessary, prefer `has_errors` or - /// `has_errors_or_lint_errors` to this method. + /// This excludes stashed errors. Unless absolutely necessary, prefer + /// `has_errors` or `has_errors_or_lint_errors` to this method. pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option { let inner = self.inner.borrow(); let result = @@ -1224,10 +1235,8 @@ impl DiagCtxtInner { 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() { - self.lint_err_count -= 1; - } else { - self.err_count -= 1; + if diag.is_lint.is_none() { + self.stashed_err_count -= 1; } } else { // Unless they're forced, don't flush stashed warnings when diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 3430a5fb00dc9..94f6c06157efe 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -753,10 +753,14 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { } fn report_error(&self, p: impl Into>) -> ErrorGuaranteed { - match self.fcx.dcx().has_errors() { - Some(e) => e, - None => self - .fcx + if let Some(guar) = self.fcx.dcx().has_errors() { + guar + } else if self.fcx.dcx().stashed_err_count() > 0 { + // Without this case we sometimes get uninteresting and extraneous + // "type annotations needed" errors. + self.fcx.dcx().delayed_bug("error in Resolver") + } else { + self.fcx .err_ctxt() .emit_inference_failure_err( self.fcx.tcx.hir().body_owner_def_id(self.body.id()), @@ -765,7 +769,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { E0282, false, ) - .emit(), + .emit() } } diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 0f1af81d9f04c..859593e119457 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -87,6 +87,7 @@ impl<'tcx> InferCtxt<'tcx> { reported_signature_mismatch: self.reported_signature_mismatch.clone(), tainted_by_errors: self.tainted_by_errors.clone(), err_count_on_creation: self.err_count_on_creation, + stashed_err_count_on_creation: self.stashed_err_count_on_creation, universe: self.universe.clone(), intercrate, next_trait_solver: self.next_trait_solver, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2d8b47a9cc057..20bd0a6b69ab5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -306,6 +306,12 @@ pub struct InferCtxt<'tcx> { // FIXME(matthewjasper) Merge into `tainted_by_errors` err_count_on_creation: usize, + /// Track how many errors were stashed when this infcx is created. + /// Used for the same purpose as `err_count_on_creation`, even + /// though it's weaker because the count can go up and down. + // FIXME(matthewjasper) Merge into `tainted_by_errors` + stashed_err_count_on_creation: usize, + /// What is the innermost universe we have created? Starts out as /// `UniverseIndex::root()` but grows from there as we enter /// universal quantifiers. @@ -711,6 +717,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { reported_signature_mismatch: Default::default(), tainted_by_errors: Cell::new(None), err_count_on_creation: tcx.dcx().err_count(), + stashed_err_count_on_creation: tcx.dcx().stashed_err_count(), universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, next_trait_solver, @@ -1261,26 +1268,24 @@ impl<'tcx> InferCtxt<'tcx> { /// inference variables, regionck errors). #[must_use = "this method does not have any side effects"] pub fn tainted_by_errors(&self) -> Option { - debug!( - "is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ - tainted_by_errors={})", - self.dcx().err_count(), - self.err_count_on_creation, - self.tainted_by_errors.get().is_some() - ); - - if let Some(e) = self.tainted_by_errors.get() { - return Some(e); - } - - if self.dcx().err_count() > self.err_count_on_creation { - // errors reported since this infcx was made - let e = self.dcx().has_errors().unwrap(); - self.set_tainted_by_errors(e); - return Some(e); + if let Some(guar) = self.tainted_by_errors.get() { + Some(guar) + } else if self.dcx().err_count() > self.err_count_on_creation { + // Errors reported since this infcx was made. + let guar = self.dcx().has_errors().unwrap(); + self.set_tainted_by_errors(guar); + Some(guar) + } else if self.dcx().stashed_err_count() > self.stashed_err_count_on_creation { + // Errors stashed since this infcx was made. Not entirely reliable + // because the count of stashed errors can go down. But without + // this case we get a moderate number of uninteresting and + // extraneous "type annotations needed" errors. + let guar = self.dcx().delayed_bug("tainted_by_errors: stashed bug awaiting emission"); + self.set_tainted_by_errors(guar); + Some(guar) + } else { + None } - - None } /// Set the "tainted by errors" flag to true. We call this when we diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 9795640412069..50b2bf7da153e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -778,6 +778,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // kindck is gone now). -nmatsakis if let Some(reported) = sess.dcx().has_errors() { return Err(reported); + } else if sess.dcx().stashed_err_count() > 0 { + // Without this case we sometimes get delayed bug ICEs and I don't + // understand why. -nnethercote + return Err(sess.dcx().delayed_bug("some stashed error is waiting for use")); } sess.time("misc_checking_3", || { From 575e0aa592757cef5456e38be7d44126a69bf162 Mon Sep 17 00:00:00 2001 From: Nicolas Roche Date: Fri, 9 Feb 2024 09:07:49 +0100 Subject: [PATCH 676/676] Startup objects disappearing from sysroot When launching tests with --keep-stage option, startup objects such as rsbegin.o an rsend.o may disappear from the corresponding stageN compiler. Fix issue #120784 --- src/bootstrap/src/core/build_steps/compile.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 73f29d6bb6f45..27b1d311864f3 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -173,6 +173,8 @@ impl Step for Std { { builder.info("WARNING: Using a potentially old libstd. This may not behave well."); + builder.ensure(StartupObjects { compiler, target }); + self.copy_extra_objects(builder, &compiler, target); builder.ensure(StdLink::from_std(self, compiler));

` 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 424/676] 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 425/676] 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 73313158988c20b57a341502b4099629b6867755 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 30 Jan 2024 20:55:56 +0000 Subject: [PATCH 426/676] Remove `ffi_returns_twice` feature --- compiler/rustc_codegen_gcc/src/attributes.rs | 3 --- compiler/rustc_codegen_llvm/src/attributes.rs | 3 --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 - .../rustc_codegen_ssa/src/codegen_attrs.rs | 3 --- .../src/error_codes/E0724.md | 7 ++++-- compiler/rustc_feature/src/builtin_attrs.rs | 3 --- compiler/rustc_feature/src/removed.rs | 3 +++ compiler/rustc_feature/src/unstable.rs | 2 -- .../rustc_llvm/llvm-wrapper/LLVMWrapper.h | 1 - .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 2 -- .../src/middle/codegen_fn_attrs.rs | 23 ++++++++----------- compiler/rustc_passes/messages.ftl | 3 --- compiler/rustc_passes/src/check_attr.rs | 10 -------- compiler/rustc_passes/src/errors.rs | 7 ------ src/tools/tidy/src/ui_tests.rs | 2 +- tests/codegen/cffi/ffi-returns-twice.rs | 11 --------- .../feature-gate-ffi_returns_twice.rs | 6 ----- .../feature-gate-ffi_returns_twice.stderr | 13 ----------- tests/ui/ffi_returns_twice.rs | 15 ------------ tests/ui/ffi_returns_twice.stderr | 21 ----------------- 20 files changed, 19 insertions(+), 120 deletions(-) delete mode 100644 tests/codegen/cffi/ffi-returns-twice.rs delete mode 100644 tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs delete mode 100644 tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr delete mode 100644 tests/ui/ffi_returns_twice.rs delete mode 100644 tests/ui/ffi_returns_twice.stderr diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs index 9f361d3688695..142f86b003ddb 100644 --- a/compiler/rustc_codegen_gcc/src/attributes.rs +++ b/compiler/rustc_codegen_gcc/src/attributes.rs @@ -62,9 +62,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { func.add_attribute(FnAttribute::Cold); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { - func.add_attribute(FnAttribute::ReturnsTwice); - } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { func.add_attribute(FnAttribute::Pure); } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 0a7ea5994312e..07c83f1aa089a 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -356,9 +356,6 @@ pub fn from_fn_attrs<'ll, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { to_add.push(AttributeKind::Cold.create_attr(cx.llcx)); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { - to_add.push(AttributeKind::ReturnsTwice.create_attr(cx.llcx)); - } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { to_add.push(MemoryEffects::ReadOnly.create_attr(cx.llcx)); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ee73c6b4756f0..5c06c62b11a3c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -185,7 +185,6 @@ pub enum AttributeKind { SanitizeMemory = 22, NonLazyBind = 23, OptimizeNone = 24, - ReturnsTwice = 25, ReadNone = 26, SanitizeHWAddress = 28, WillReturn = 29, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 47b1b0801193a..b387d0b2258b0 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -103,9 +103,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { match name { sym::cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR, - sym::ffi_returns_twice => { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE - } sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE, sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST, sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND, diff --git a/compiler/rustc_error_codes/src/error_codes/E0724.md b/compiler/rustc_error_codes/src/error_codes/E0724.md index 70578acbe0d5f..bcefd0a74798b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0724.md +++ b/compiler/rustc_error_codes/src/error_codes/E0724.md @@ -1,9 +1,12 @@ +#### Note: this error code is no longer emitted by the compiler. + + `#[ffi_returns_twice]` was used on something other than a foreign function declaration. Erroneous code example: -```compile_fail,E0724 +```compile_fail #![feature(ffi_returns_twice)] #![crate_type = "lib"] @@ -15,7 +18,7 @@ pub fn foo() {} For example, we might correct the previous example by declaring the function inside of an `extern` block. -``` +```compile_fail #![feature(ffi_returns_twice)] extern "C" { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 68b6f69854dd6..019cc1c847e91 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -440,9 +440,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ experimental!(optimize), ), - gated!( - ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice) - ), gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)), gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)), gated!( diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 67ee53d8ae53f..dc97898736808 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -95,6 +95,9 @@ declare_features! ( /// Allows `#[doc(include = "some-file")]`. (removed, external_doc, "1.54.0", Some(44732), Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), + /// Allows using `#[ffi_returns_twice]` on foreign functions. + (removed, ffi_returns_twice, "CURRENT_RUSTC_VERSION", Some(58314), + Some("being investigated by the ffi-unwind project group")), /// Allows generators to be cloned. (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")), /// Allows defining generators. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e66a66e23dc4f..0efc031df0aa6 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -467,8 +467,6 @@ declare_features! ( (unstable, ffi_const, "1.45.0", Some(58328)), /// Allows the use of `#[ffi_pure]` on foreign functions. (unstable, ffi_pure, "1.45.0", Some(58329)), - /// Allows using `#[ffi_returns_twice]` on foreign functions. - (unstable, ffi_returns_twice, "1.34.0", Some(58314)), /// Allows using `#[repr(align(...))]` on function items (unstable, fn_align, "1.53.0", Some(82232)), /// Support delegating implementation of functions to other already implemented functions. diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 5bfffc5d9117b..6d578c97f3fe1 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -76,7 +76,6 @@ enum LLVMRustAttribute { SanitizeMemory = 22, NonLazyBind = 23, OptimizeNone = 24, - ReturnsTwice = 25, ReadNone = 26, SanitizeHWAddress = 28, WillReturn = 29, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 0df7b7eed11f9..a2dfebec59441 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -250,8 +250,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::NonLazyBind; case OptimizeNone: return Attribute::OptimizeNone; - case ReturnsTwice: - return Attribute::ReturnsTwice; case ReadNone: return Attribute::ReadNone; case SanitizeHWAddress: diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index e11c9371118cb..7d6d39a2a8a39 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -74,35 +74,32 @@ bitflags! { /// `#[used]`: indicates that LLVM can't eliminate this function (but the /// linker can!). const USED = 1 << 9; - /// `#[ffi_returns_twice]`, indicates that an extern function can return - /// multiple times - const FFI_RETURNS_TWICE = 1 << 10; /// `#[track_caller]`: allow access to the caller location - const TRACK_CALLER = 1 << 11; + const TRACK_CALLER = 1 << 10; /// #[ffi_pure]: applies clang's `pure` attribute to a foreign function /// declaration. - const FFI_PURE = 1 << 12; + const FFI_PURE = 1 << 11; /// #[ffi_const]: applies clang's `const` attribute to a foreign function /// declaration. - const FFI_CONST = 1 << 13; + const FFI_CONST = 1 << 12; /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a /// function as an entry function from Non-Secure code. - const CMSE_NONSECURE_ENTRY = 1 << 14; + const CMSE_NONSECURE_ENTRY = 1 << 13; /// `#[coverage(off)]`: indicates that the function should be ignored by /// the MIR `InstrumentCoverage` pass and not added to the coverage map /// during codegen. - const NO_COVERAGE = 1 << 15; + const NO_COVERAGE = 1 << 14; /// `#[used(linker)]`: /// indicates that neither LLVM nor the linker will eliminate this function. - const USED_LINKER = 1 << 16; + const USED_LINKER = 1 << 15; /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory. - const DEALLOCATOR = 1 << 17; + const DEALLOCATOR = 1 << 16; /// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory. - const REALLOCATOR = 1 << 18; + const REALLOCATOR = 1 << 17; /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory. - const ALLOCATOR_ZEROED = 1 << 19; + const ALLOCATOR_ZEROED = 1 << 18; /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function. - const NO_BUILTINS = 1 << 20; + const NO_BUILTINS = 1 << 19; } } rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index d41cc724408a4..648ef9d51deaa 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -323,9 +323,6 @@ passes_ffi_const_invalid_target = passes_ffi_pure_invalid_target = `#[ffi_pure]` may only be used on foreign functions -passes_ffi_returns_twice_invalid_target = - `#[ffi_returns_twice]` may only be used on foreign functions - passes_has_incoherent_inherent_impl = `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits. .label = only adts, extern types and traits are supported diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8f27d01794cc6..51725285bd7ac 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -190,7 +190,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target), sym::ffi_const => self.check_ffi_const(attr.span, target), - sym::ffi_returns_twice => self.check_ffi_returns_twice(attr.span, target), sym::rustc_const_unstable | sym::rustc_const_stable | sym::unstable @@ -1307,15 +1306,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_ffi_returns_twice(&self, attr_span: Span, target: Target) -> bool { - if target == Target::ForeignFn { - true - } else { - self.dcx().emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span }); - false - } - } - /// Warns against some misuses of `#[must_use]` fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool { if !matches!( diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 77bfe57e3706f..6a499a98681e6 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -390,13 +390,6 @@ pub struct FfiConstInvalidTarget { pub attr_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_ffi_returns_twice_invalid_target, code = E0724)] -pub struct FfiReturnsTwiceInvalidTarget { - #[primary_span] - pub attr_span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_must_use_async)] pub struct MustUseAsync { diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 451276b5ac157..094694274269f 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -14,7 +14,7 @@ use std::path::{Path, PathBuf}; // #73494. const ENTRY_LIMIT: usize = 900; const ISSUES_ENTRY_LIMIT: usize = 1807; -const ROOT_ENTRY_LIMIT: usize = 870; +const ROOT_ENTRY_LIMIT: usize = 868; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/codegen/cffi/ffi-returns-twice.rs b/tests/codegen/cffi/ffi-returns-twice.rs deleted file mode 100644 index 0fbe03f0bb6f1..0000000000000 --- a/tests/codegen/cffi/ffi-returns-twice.rs +++ /dev/null @@ -1,11 +0,0 @@ -// compile-flags: -C no-prepopulate-passes -#![crate_type = "lib"] -#![feature(ffi_returns_twice)] - -pub fn bar() { unsafe { foo() } } - -extern "C" { - // CHECK: declare{{( dso_local)?}} void @foo(){{.*}}[[ATTRS:#[0-9]+]] - // CHECK: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} } - #[ffi_returns_twice] pub fn foo(); -} diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs deleted file mode 100644 index f354534356c21..0000000000000 --- a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![crate_type = "lib"] - -extern "C" { - #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature - pub fn foo(); -} diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr deleted file mode 100644 index 8d19874c36a0c..0000000000000 --- a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature - --> $DIR/feature-gate-ffi_returns_twice.rs:4:5 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #58314 for more information - = help: add `#![feature(ffi_returns_twice)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/ffi_returns_twice.rs b/tests/ui/ffi_returns_twice.rs deleted file mode 100644 index 8195d0e486369..0000000000000 --- a/tests/ui/ffi_returns_twice.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(ffi_returns_twice)] -#![crate_type = "lib"] - -#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions -pub fn foo() {} - -#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions -macro_rules! bar { - () => () -} - -extern "C" { - #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions - static INT: i32; -} diff --git a/tests/ui/ffi_returns_twice.stderr b/tests/ui/ffi_returns_twice.stderr deleted file mode 100644 index 0abe7613f1493..0000000000000 --- a/tests/ui/ffi_returns_twice.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:4:1 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:7:1 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:13:5 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0724`. From 15b473451cce5237ccff6cad85836ecf203475e8 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 31 Jan 2024 00:58:22 +0100 Subject: [PATCH 427/676] 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 428/676] 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 429/676] 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 430/676] 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 f622e832d41171578b6987d0b25b3a84d6d1c81c Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Wed, 24 Jan 2024 15:57:43 -0800 Subject: [PATCH 431/676] Actually abort in panic-abort-tests --- Cargo.lock | 1 + library/test/Cargo.toml | 1 + library/test/src/helpers/exit_code.rs | 20 --------------- library/test/src/helpers/mod.rs | 1 - library/test/src/lib.rs | 15 ++--------- library/test/src/test_result.rs | 36 +++++++++++++++++++++------ 6 files changed, 33 insertions(+), 41 deletions(-) delete mode 100644 library/test/src/helpers/exit_code.rs diff --git a/Cargo.lock b/Cargo.lock index 74f96983b3149..24054e8592e2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5332,6 +5332,7 @@ version = "0.0.0" dependencies = [ "core", "getopts", + "libc", "panic_abort", "panic_unwind", "std", diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 92c535501bf9c..4c42e3bae563e 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -9,3 +9,4 @@ std = { path = "../std" } core = { path = "../core" } panic_unwind = { path = "../panic_unwind" } panic_abort = { path = "../panic_abort" } +libc = { version = "0.2.150", default-features = false } diff --git a/library/test/src/helpers/exit_code.rs b/library/test/src/helpers/exit_code.rs deleted file mode 100644 index f762f88819da5..0000000000000 --- a/library/test/src/helpers/exit_code.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Helper module to detect subprocess exit code. - -use std::process::ExitStatus; - -#[cfg(not(unix))] -pub fn get_exit_code(status: ExitStatus) -> Result { - status.code().ok_or_else(|| "received no exit code from child process".into()) -} - -#[cfg(unix)] -pub fn get_exit_code(status: ExitStatus) -> Result { - use std::os::unix::process::ExitStatusExt; - match status.code() { - Some(code) => Ok(code), - None => match status.signal() { - Some(signal) => Err(format!("child process exited with signal {signal}")), - None => Err("child process exited with unknown signal".into()), - }, - } -} diff --git a/library/test/src/helpers/mod.rs b/library/test/src/helpers/mod.rs index 6f366a911e8cd..3c79b90b16754 100644 --- a/library/test/src/helpers/mod.rs +++ b/library/test/src/helpers/mod.rs @@ -2,6 +2,5 @@ //! but used in `libtest`. pub mod concurrency; -pub mod exit_code; pub mod metrics; pub mod shuffle; diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 5969d6b772c34..da110f9924861 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -85,7 +85,6 @@ mod tests; use core::any::Any; use event::{CompletedTest, TestEvent}; use helpers::concurrency::get_concurrency; -use helpers::exit_code::get_exit_code; use helpers::shuffle::{get_shuffle_seed, shuffle_tests}; use options::RunStrategy; use test_result::*; @@ -712,17 +711,7 @@ fn spawn_test_subprocess( formatters::write_stderr_delimiter(&mut test_output, &desc.name); test_output.extend_from_slice(&stderr); - let result = match (|| -> Result { - let exit_code = get_exit_code(status)?; - Ok(get_result_from_exit_code(&desc, exit_code, &time_opts, &exec_time)) - })() { - Ok(r) => r, - Err(e) => { - write!(&mut test_output, "Unexpected error: {e}").unwrap(); - TrFailed - } - }; - + let result = get_result_from_exit_code(&desc, status, &time_opts, &exec_time); (result, test_output, exec_time) })(); @@ -751,7 +740,7 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) - if let TrOk = test_result { process::exit(test_result::TR_OK); } else { - process::exit(test_result::TR_FAILED); + process::abort(); } }); let record_result2 = record_result.clone(); diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index 1da238e3e8c0f..bb32c70d66311 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -1,4 +1,8 @@ use std::any::Any; +use std::process::ExitStatus; + +#[cfg(unix)] +use std::os::unix::process::ExitStatusExt; use super::bench::BenchSamples; use super::options::ShouldPanic; @@ -7,11 +11,15 @@ use super::types::TestDesc; pub use self::TestResult::*; -// Return codes for secondary process. +// Return code for secondary process. // Start somewhere other than 0 so we know the return code means what we think // it means. pub const TR_OK: i32 = 50; -pub const TR_FAILED: i32 = 51; + +// On Windows we use __fastfail to abort, which is documented to use this +// exception code. +#[cfg(windows)] +const STATUS_ABORTED: i32 = 0xC0000409u32 as i32; #[derive(Debug, Clone, PartialEq)] pub enum TestResult { @@ -81,14 +89,28 @@ pub fn calc_result<'a>( /// Creates a `TestResult` depending on the exit code of test subprocess. pub fn get_result_from_exit_code( desc: &TestDesc, - code: i32, + status: ExitStatus, time_opts: &Option, exec_time: &Option, ) -> TestResult { - let result = match code { - TR_OK => TestResult::TrOk, - TR_FAILED => TestResult::TrFailed, - _ => TestResult::TrFailedMsg(format!("got unexpected return code {code}")), + let result = match status.code() { + Some(TR_OK) => TestResult::TrOk, + #[cfg(windows)] + Some(STATUS_ABORTED) => TestResult::TrFailed, + #[cfg(unix)] + None => match status.signal() { + Some(libc::SIGABRT) => TestResult::TrFailed, + Some(signal) => { + TestResult::TrFailedMsg(format!("child process exited with signal {signal}")) + } + None => unreachable!("status.code() returned None but status.signal() was None"), + }, + #[cfg(not(unix))] + None => TestResult::TrFailedMsg(format!("unknown return code")), + #[cfg(any(windows, unix))] + Some(code) => TestResult::TrFailedMsg(format!("got unexpected return code {code}")), + #[cfg(not(any(windows, unix)))] + Some(_) => TestResult::TrFailed, }; // If test is already failed (or allowed to fail), do not change the result. From 604479c3734e2e6d44f668c69963e8d73879e0d8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 31 Jan 2024 09:16:30 +0100 Subject: [PATCH 432/676] 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 433/676] 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 434/676] 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 435/676] 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 3cc601ac7e43752e0514c6e1cb2415e781c8e666 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Wed, 31 Jan 2024 13:36:37 +0000 Subject: [PATCH 436/676] Switch OwnedStore handle count to AtomicU32 --- library/proc_macro/src/bridge/client.rs | 9 +++++---- library/proc_macro/src/bridge/handle.rs | 10 +++++----- library/proc_macro/src/bridge/mod.rs | 1 - 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 52a08cad9110f..9255c3abc8a02 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -3,6 +3,7 @@ use super::*; use std::marker::PhantomData; +use std::sync::atomic::AtomicU32; macro_rules! define_handles { ( @@ -12,8 +13,8 @@ macro_rules! define_handles { #[repr(C)] #[allow(non_snake_case)] pub struct HandleCounters { - $($oty: AtomicUsize,)* - $($ity: AtomicUsize,)* + $($oty: AtomicU32,)* + $($ity: AtomicU32,)* } impl HandleCounters { @@ -21,8 +22,8 @@ macro_rules! define_handles { // a wrapper `fn` pointer, once `const fn` can reference `static`s. extern "C" fn get() -> &'static Self { static COUNTERS: HandleCounters = HandleCounters { - $($oty: AtomicUsize::new(1),)* - $($ity: AtomicUsize::new(1),)* + $($oty: AtomicU32::new(1),)* + $($ity: AtomicU32::new(1),)* }; &COUNTERS } diff --git a/library/proc_macro/src/bridge/handle.rs b/library/proc_macro/src/bridge/handle.rs index 00954107b7769..b3a763069974f 100644 --- a/library/proc_macro/src/bridge/handle.rs +++ b/library/proc_macro/src/bridge/handle.rs @@ -4,7 +4,7 @@ use std::collections::BTreeMap; use std::hash::Hash; use std::num::NonZeroU32; use std::ops::{Index, IndexMut}; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicU32, Ordering}; use super::fxhash::FxHashMap; @@ -13,12 +13,12 @@ pub(super) type Handle = NonZeroU32; /// A store that associates values of type `T` with numeric handles. A value can /// be looked up using its handle. pub(super) struct OwnedStore { - counter: &'static AtomicUsize, + counter: &'static AtomicU32, data: BTreeMap, } impl OwnedStore { - pub(super) fn new(counter: &'static AtomicUsize) -> Self { + pub(super) fn new(counter: &'static AtomicU32) -> Self { // Ensure the handle counter isn't 0, which would panic later, // when `NonZeroU32::new` (aka `Handle::new`) is called in `alloc`. assert_ne!(counter.load(Ordering::SeqCst), 0); @@ -30,7 +30,7 @@ impl OwnedStore { impl OwnedStore { pub(super) fn alloc(&mut self, x: T) -> Handle { let counter = self.counter.fetch_add(1, Ordering::SeqCst); - let handle = Handle::new(counter as u32).expect("`proc_macro` handle counter overflowed"); + let handle = Handle::new(counter).expect("`proc_macro` handle counter overflowed"); assert!(self.data.insert(handle, x).is_none()); handle } @@ -60,7 +60,7 @@ pub(super) struct InternedStore { } impl InternedStore { - pub(super) fn new(counter: &'static AtomicUsize) -> Self { + pub(super) fn new(counter: &'static AtomicU32) -> Self { InternedStore { owned: OwnedStore::new(counter), interner: FxHashMap::default() } } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 75bf3329786a4..55e24b6491c79 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -16,7 +16,6 @@ use std::mem; use std::ops::Bound; use std::ops::Range; use std::panic; -use std::sync::atomic::AtomicUsize; use std::sync::Once; use std::thread; From 7ea4dbbadbec741358b282ee44ebcd62805ecc41 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Wed, 31 Jan 2024 13:58:52 +0000 Subject: [PATCH 437/676] 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 438/676] 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 439/676] 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 440/676] 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 441/676] 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 442/676] 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 443/676] 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 444/676] 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 445/676] 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 446/676] 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 447/676] 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 448/676] 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 449/676] 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 450/676] 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 451/676] 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 452/676] 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 453/676] 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 454/676] 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 455/676] 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 456/676] 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 457/676] 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 458/676] 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 459/676] 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 460/676] 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 461/676] 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 462/676] 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 463/676] 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 464/676] 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 465/676] 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 466/676] `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 467/676] 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 468/676] 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 be77cf86bae2b8a9c94eb93092d1b05230b17e8c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 25 Jan 2024 03:37:24 +0100 Subject: [PATCH 469/676] Use a `Vec` instead of a slice in `DeconstructedPat` --- compiler/rustc_pattern_analysis/src/lib.rs | 8 +-- compiler/rustc_pattern_analysis/src/pat.rs | 32 ++++++----- .../rustc_pattern_analysis/src/pat_column.rs | 4 +- compiler/rustc_pattern_analysis/src/rustc.rs | 57 ++++++++----------- .../rustc_pattern_analysis/src/usefulness.rs | 4 +- 5 files changed, 51 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 3d0eb117d174f..cef2fe1621500 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -119,7 +119,7 @@ pub trait TypeCx: Sized + fmt::Debug { /// `DeconstructedPat`. Only invoqued when `pat.ctor()` is `Struct | Variant(_) | UnionField`. fn write_variant_name( f: &mut fmt::Formatter<'_>, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat, ) -> fmt::Result; /// Raise a bug. @@ -130,9 +130,9 @@ pub trait TypeCx: Sized + fmt::Debug { /// The default implementation does nothing. fn lint_overlapping_range_endpoints( &self, - _pat: &DeconstructedPat<'_, Self>, + _pat: &DeconstructedPat, _overlaps_on: IntRange, - _overlaps_with: &[&DeconstructedPat<'_, Self>], + _overlaps_with: &[&DeconstructedPat], ) { } } @@ -140,7 +140,7 @@ pub trait TypeCx: Sized + fmt::Debug { /// The arm of a match expression. #[derive(Debug)] pub struct MatchArm<'p, Cx: TypeCx> { - pub pat: &'p DeconstructedPat<'p, Cx>, + pub pat: &'p DeconstructedPat, pub has_guard: bool, pub arm_data: Cx::ArmData, } diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index c94d8b9353589..0b239b5a36238 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -6,7 +6,7 @@ use std::fmt; use smallvec::{smallvec, SmallVec}; use crate::constructor::{Constructor, Slice, SliceKind}; -use crate::{Captures, TypeCx}; +use crate::TypeCx; use self::Constructor::*; @@ -21,9 +21,9 @@ use self::Constructor::*; /// 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`. Care must /// be taken when converting to/from `thir::Pat`. -pub struct DeconstructedPat<'p, Cx: TypeCx> { +pub struct DeconstructedPat { ctor: Constructor, - fields: &'p [DeconstructedPat<'p, Cx>], + fields: Vec>, ty: Cx::Ty, /// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not /// correspond to a user-supplied pattern. @@ -32,14 +32,20 @@ pub struct DeconstructedPat<'p, Cx: TypeCx> { useful: Cell, } -impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { +impl DeconstructedPat { pub fn wildcard(ty: Cx::Ty) -> Self { - DeconstructedPat { ctor: Wildcard, fields: &[], ty, data: None, useful: Cell::new(false) } + DeconstructedPat { + ctor: Wildcard, + fields: Vec::new(), + ty, + data: None, + useful: Cell::new(false), + } } pub fn new( ctor: Constructor, - fields: &'p [DeconstructedPat<'p, Cx>], + fields: Vec>, ty: Cx::Ty, data: Cx::PatData, ) -> Self { @@ -62,17 +68,17 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { self.data.as_ref() } - pub fn iter_fields(&self) -> impl Iterator> + Captures<'_> { + pub fn iter_fields<'a>(&'a self) -> impl Iterator> { self.fields.iter() } /// Specialize this pattern with a constructor. /// `other_ctor` can be different from `self.ctor`, but must be covered by it. - pub(crate) fn specialize( - &self, + pub(crate) fn specialize<'a>( + &'a self, other_ctor: &Constructor, ctor_arity: usize, - ) -> SmallVec<[PatOrWild<'p, Cx>; 2]> { + ) -> SmallVec<[PatOrWild<'a, Cx>; 2]> { let wildcard_sub_tys = || (0..ctor_arity).map(|_| PatOrWild::Wild).collect(); match (&self.ctor, other_ctor) { // Return a wildcard for each field of `other_ctor`. @@ -139,7 +145,7 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { } /// This is best effort and not good enough for a `Display` impl. -impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> { +impl fmt::Debug for DeconstructedPat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let pat = self; let mut first = true; @@ -221,7 +227,7 @@ pub(crate) enum PatOrWild<'p, Cx: TypeCx> { /// A non-user-provided wildcard, created during specialization. Wild, /// A user-provided pattern. - Pat(&'p DeconstructedPat<'p, Cx>), + Pat(&'p DeconstructedPat), } impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { @@ -236,7 +242,7 @@ impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { impl<'p, Cx: TypeCx> Copy for PatOrWild<'p, Cx> {} impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { - pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<'p, Cx>> { + pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat> { match self { PatOrWild::Wild => None, PatOrWild::Pat(pat) => Some(pat), diff --git a/compiler/rustc_pattern_analysis/src/pat_column.rs b/compiler/rustc_pattern_analysis/src/pat_column.rs index 3cacfc491b981..d5db4bf4a342e 100644 --- a/compiler/rustc_pattern_analysis/src/pat_column.rs +++ b/compiler/rustc_pattern_analysis/src/pat_column.rs @@ -13,7 +13,7 @@ use crate::{Captures, MatchArm, TypeCx}; #[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>>, + patterns: Vec<&'p DeconstructedPat>, } impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { @@ -41,7 +41,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { 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> { + pub fn iter<'a>(&'a self) -> impl Iterator> + Captures<'a> { self.patterns.iter().copied() } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index ec37e20211860..431b7f4a31265 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,4 +1,3 @@ -use smallvec::SmallVec; use std::fmt; use std::iter::once; @@ -27,8 +26,7 @@ use crate::constructor::Constructor::*; pub type Constructor<'p, 'tcx> = crate::constructor::Constructor>; pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet>; -pub type DeconstructedPat<'p, 'tcx> = - crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>; +pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = @@ -458,21 +456,20 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { /// Note: the input patterns must have been lowered through /// `rustc_mir_build::thir::pattern::check_match::MatchVisitor::lower_pattern`. pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> { - let singleton = |pat| std::slice::from_ref(self.pattern_arena.alloc(pat)); let cx = self; let ty = cx.reveal_opaque_ty(pat.ty); let ctor; - let fields: &[_]; + let mut fields: Vec<_>; match &pat.kind { PatKind::AscribeUserType { subpattern, .. } | PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; - fields = &[]; + fields = vec![]; } PatKind::Deref { subpattern } => { - fields = singleton(self.lower_pat(subpattern)); + fields = vec![self.lower_pat(subpattern)]; ctor = match ty.kind() { // This is a box pattern. ty::Adt(adt, ..) if adt.is_box() => Struct, @@ -484,15 +481,14 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { match ty.kind() { ty::Tuple(fs) => { ctor = Struct; - let mut wilds: SmallVec<[_; 2]> = fs + fields = fs .iter() .map(|ty| cx.reveal_opaque_ty(ty)) .map(|ty| DeconstructedPat::wildcard(ty)) .collect(); for pat in subpatterns { - wilds[pat.field.index()] = self.lower_pat(&pat.pattern); + fields[pat.field.index()] = self.lower_pat(&pat.pattern); } - fields = cx.pattern_arena.alloc_from_iter(wilds); } ty::Adt(adt, args) if adt.is_box() => { // The only legal patterns of type `Box` (outside `std`) are `_` and box @@ -514,7 +510,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { DeconstructedPat::wildcard(self.reveal_opaque_ty(args.type_at(0))) }; ctor = Struct; - fields = singleton(pat); + fields = vec![pat]; } ty::Adt(adt, _) => { ctor = match pat.kind { @@ -534,14 +530,12 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { ty }, ); - let mut wilds: SmallVec<[_; 2]> = - tys.map(|ty| DeconstructedPat::wildcard(ty)).collect(); + fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect(); for pat in subpatterns { if let Some(i) = field_id_to_id[pat.field.index()] { - wilds[i] = self.lower_pat(&pat.pattern); + fields[i] = self.lower_pat(&pat.pattern); } } - fields = cx.pattern_arena.alloc_from_iter(wilds); } _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty), } @@ -553,7 +547,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { Some(b) => Bool(b), None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Char | ty::Int(_) | ty::Uint(_) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -569,7 +563,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Float(ty::FloatTy::F32) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -580,7 +574,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Float(ty::FloatTy::F64) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -591,7 +585,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Ref(_, t, _) if t.is_str() => { // We want a `&str` constant to behave like a `Deref` pattern, to be compatible @@ -602,16 +596,16 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { // subfields. // Note: `t` is `str`, not `&str`. let ty = self.reveal_opaque_ty(*t); - let subpattern = DeconstructedPat::new(Str(*value), &[], ty, pat); + let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), ty, pat); ctor = Ref; - fields = singleton(subpattern) + fields = vec![subpattern] } // All constants that can be structurally matched have already been expanded // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are // opaque. _ => { ctor = Opaque(OpaqueId::new()); - fields = &[]; + fields = vec![]; } } } @@ -648,7 +642,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } _ => bug!("invalid type for range pattern: {}", ty.inner()), }; - fields = &[]; + fields = vec![]; } PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { let array_len = match ty.kind() { @@ -664,25 +658,22 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { SliceKind::FixedLen(prefix.len() + suffix.len()) }; ctor = Slice(Slice::new(array_len, kind)); - fields = cx.pattern_arena.alloc_from_iter( - prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)), - ) + fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect(); } PatKind::Or { .. } => { ctor = Or; let pats = expand_or_pat(pat); - fields = - cx.pattern_arena.alloc_from_iter(pats.into_iter().map(|p| self.lower_pat(p))) + fields = pats.into_iter().map(|p| self.lower_pat(p)).collect(); } PatKind::Never => { // FIXME(never_patterns): handle `!` in exhaustiveness. This is a sane default // in the meantime. ctor = Wildcard; - fields = &[]; + fields = vec![]; } PatKind::Error(_) => { ctor = Opaque(OpaqueId::new()); - fields = &[]; + fields = vec![]; } } DeconstructedPat::new(ctor, fields, ty, pat) @@ -887,7 +878,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn write_variant_name( f: &mut fmt::Formatter<'_>, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat, ) -> fmt::Result { if let ty::Adt(adt, _) = pat.ty().kind() { if adt.is_box() { @@ -906,9 +897,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn lint_overlapping_range_endpoints( &self, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat, overlaps_on: IntRange, - overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>], + overlaps_with: &[&crate::pat::DeconstructedPat], ) { let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); let overlaps: Vec<_> = overlaps_with diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 3d45d032a9934..28600d6309781 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -848,7 +848,7 @@ impl<'p, Cx: TypeCx> Clone for PatStack<'p, Cx> { } impl<'p, Cx: TypeCx> PatStack<'p, Cx> { - fn from_pattern(pat: &'p DeconstructedPat<'p, Cx>) -> Self { + fn from_pattern(pat: &'p DeconstructedPat) -> Self { PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true } } @@ -1585,7 +1585,7 @@ pub enum Usefulness<'p, Cx: TypeCx> { /// The arm is useful. This additionally carries a set of or-pattern branches that have been /// found to be redundant despite the overall arm being useful. Used only in the presence of /// or-patterns, otherwise it stays empty. - Useful(Vec<&'p DeconstructedPat<'p, Cx>>), + Useful(Vec<&'p DeconstructedPat>), /// The arm is redundant and can be removed without changing the behavior of the match /// expression. Redundant, From f65fe3ba59286710324abb9860667f1ecf805df9 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 25 Jan 2024 04:35:09 +0100 Subject: [PATCH 470/676] Remove `pattern_arena` from `RustcMatchCheckCtxt` --- .../rustc_mir_build/src/thir/pattern/check_match.rs | 3 +-- compiler/rustc_pattern_analysis/src/errors.rs | 5 ++++- compiler/rustc_pattern_analysis/src/rustc.rs | 12 +++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index caf7f4227dbf8..1156e8be13e74 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -291,7 +291,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { err = err.and(check_never_pattern(cx, pat)); }); err?; - Ok(cx.pattern_arena.alloc(cx.lower_pat(pat))) + Ok(self.pattern_arena.alloc(cx.lower_pat(pat))) } } @@ -388,7 +388,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { typeck_results: self.typeck_results, param_env: self.param_env, module: self.tcx.parent_module(self.lint_level).to_def_id(), - pattern_arena: self.pattern_arena, dropless_arena: self.dropless_arena, match_lint_level: self.lint_level, whole_match_span, diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 88770b0c43b37..bdb6cf19eac4e 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -23,7 +23,10 @@ impl<'tcx> Uncovered<'tcx> { span: Span, cx: &RustcMatchCheckCtxt<'p, 'tcx>, witnesses: Vec>, - ) -> Self { + ) -> Self + where + 'tcx: 'p, + { let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap()); Self { span, diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 431b7f4a31265..5334857343f91 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,7 +1,7 @@ use std::fmt; use std::iter::once; -use rustc_arena::{DroplessArena, TypedArena}; +use rustc_arena::DroplessArena; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::{Idx, IndexVec}; @@ -62,7 +62,7 @@ impl<'tcx> RevealedTy<'tcx> { } #[derive(Clone)] -pub struct RustcMatchCheckCtxt<'p, 'tcx> { +pub struct RustcMatchCheckCtxt<'p, 'tcx: 'p> { pub tcx: TyCtxt<'tcx>, pub typeck_results: &'tcx ty::TypeckResults<'tcx>, /// The module in which the match occurs. This is necessary for @@ -72,8 +72,6 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> { /// outside its module and should not be matchable with an empty match statement. pub module: DefId, pub param_env: ty::ParamEnv<'tcx>, - /// To allocate lowered patterns - pub pattern_arena: &'p TypedArena>, /// To allocate the result of `self.ctor_sub_tys()` pub dropless_arena: &'p DroplessArena, /// Lint level at the match. @@ -89,13 +87,13 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> { pub known_valid_scrutinee: bool, } -impl<'p, 'tcx> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RustcMatchCheckCtxt").finish() } } -impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { /// Type inference occasionally gives us opaque types in places where corresponding patterns /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited /// types, we use the corresponding concrete type if possible. @@ -844,7 +842,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } } -impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { type Ty = RevealedTy<'tcx>; type Error = ErrorGuaranteed; type VariantIdx = VariantIdx; From a1fdb876c34e7ad7ae36cfd49fd939e1fde00aa6 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 31 Jan 2024 19:06:10 +0000 Subject: [PATCH 471/676] 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 472/676] 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 473/676] 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 474/676] 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 475/676] 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 476/676] 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 477/676] 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 478/676] 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 479/676] 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 480/676] 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 481/676] 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 482/676] `#![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 483/676] 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 484/676] 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 485/676] 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 486/676] 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 487/676] 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 488/676] 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 489/676] 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 490/676] 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 491/676] 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 2e212b79e09bce189a787a5b0c05ee5318e3c574 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 25 Jan 2024 13:35:40 +1100 Subject: [PATCH 492/676] coverage: Split out counter increment sites from BCB node/edge counters This makes it possible for two nodes/edges in the coverage graph to share the same counter, without causing the instrumentor to inject unwanted duplicate counter-increment statements. --- .../src/coverage/counters.rs | 70 ++++++++------- .../rustc_mir_transform/src/coverage/mod.rs | 89 +++++++++---------- 2 files changed, 79 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 8c11dea5d4ee6..9a1d8bae6b410 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -1,4 +1,5 @@ -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::captures::Captures; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::WithNumNodes; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -38,19 +39,27 @@ impl Debug for BcbCounter { } } +#[derive(Debug)] +pub(super) enum CounterIncrementSite { + Node { bcb: BasicCoverageBlock }, + Edge { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock }, +} + /// Generates and stores coverage counter and coverage expression information /// associated with nodes/edges in the BCB graph. pub(super) struct CoverageCounters { - next_counter_id: CounterId, + /// List of places where a counter-increment statement should be injected + /// into MIR, each with its corresponding counter ID. + counter_increment_sites: IndexVec, /// Coverage counters/expressions that are associated with individual BCBs. bcb_counters: IndexVec>, /// Coverage counters/expressions that are associated with the control-flow /// edge between two BCBs. /// - /// The iteration order of this map can affect the precise contents of MIR, - /// so we use `FxIndexMap` to avoid query stability hazards. - bcb_edge_counters: FxIndexMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, + /// We currently don't iterate over this map, but if we do in the future, + /// switch it back to `FxIndexMap` to avoid query stability hazards. + bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, /// Tracks which BCBs have a counter associated with some incoming edge. /// Only used by assertions, to verify that BCBs with incoming edge /// counters do not have their own physical counters (expressions are allowed). @@ -71,9 +80,9 @@ impl CoverageCounters { let num_bcbs = basic_coverage_blocks.num_nodes(); let mut this = Self { - next_counter_id: CounterId::START, + counter_increment_sites: IndexVec::new(), bcb_counters: IndexVec::from_elem_n(None, num_bcbs), - bcb_edge_counters: FxIndexMap::default(), + bcb_edge_counters: FxHashMap::default(), bcb_has_incoming_edge_counters: BitSet::new_empty(num_bcbs), expressions: IndexVec::new(), }; @@ -84,8 +93,8 @@ impl CoverageCounters { this } - fn make_counter(&mut self) -> BcbCounter { - let id = self.next_counter(); + fn make_counter(&mut self, site: CounterIncrementSite) -> BcbCounter { + let id = self.counter_increment_sites.push(site); BcbCounter::Counter { id } } @@ -103,15 +112,8 @@ impl CoverageCounters { self.make_expression(lhs, Op::Add, rhs) } - /// Counter IDs start from one and go up. - fn next_counter(&mut self) -> CounterId { - let next = self.next_counter_id; - self.next_counter_id = self.next_counter_id + 1; - next - } - pub(super) fn num_counters(&self) -> usize { - self.next_counter_id.as_usize() + self.counter_increment_sites.len() } #[cfg(test)] @@ -171,22 +173,26 @@ impl CoverageCounters { self.bcb_counters[bcb] } - pub(super) fn bcb_node_counters( + /// Returns an iterator over all the nodes/edges in the coverage graph that + /// should have a counter-increment statement injected into MIR, along with + /// each site's corresponding counter ID. + pub(super) fn counter_increment_sites( &self, - ) -> impl Iterator { - self.bcb_counters - .iter_enumerated() - .filter_map(|(bcb, counter_kind)| Some((bcb, counter_kind.as_ref()?))) + ) -> impl Iterator { + self.counter_increment_sites.iter_enumerated() } - /// For each edge in the BCB graph that has an associated counter, yields - /// that edge's *from* and *to* nodes, and its counter. - pub(super) fn bcb_edge_counters( + /// Returns an iterator over the subset of BCB nodes that have been associated + /// with a counter *expression*, along with the ID of that expression. + pub(super) fn bcb_nodes_with_coverage_expressions( &self, - ) -> impl Iterator { - self.bcb_edge_counters - .iter() - .map(|(&(from_bcb, to_bcb), counter_kind)| (from_bcb, to_bcb, counter_kind)) + ) -> impl Iterator + Captures<'_> { + self.bcb_counters.iter_enumerated().filter_map(|(bcb, &counter_kind)| match counter_kind { + // Yield the BCB along with its associated expression ID. + Some(BcbCounter::Expression { id }) => Some((bcb, id)), + // This BCB is associated with a counter or nothing, so skip it. + Some(BcbCounter::Counter { .. }) | None => None, + }) } pub(super) fn into_expressions(self) -> IndexVec { @@ -339,7 +345,8 @@ impl<'a> MakeBcbCounters<'a> { // program results in a tight infinite loop, but it should still compile. let one_path_to_target = !self.basic_coverage_blocks.bcb_has_multiple_in_edges(bcb); if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) { - let counter_kind = self.coverage_counters.make_counter(); + let counter_kind = + self.coverage_counters.make_counter(CounterIncrementSite::Node { bcb }); if one_path_to_target { debug!("{bcb:?} gets a new counter: {counter_kind:?}"); } else { @@ -401,7 +408,8 @@ impl<'a> MakeBcbCounters<'a> { } // Make a new counter to count this edge. - let counter_kind = self.coverage_counters.make_counter(); + let counter_kind = + self.coverage_counters.make_counter(CounterIncrementSite::Edge { from_bcb, to_bcb }); debug!("Edge {from_bcb:?}->{to_bcb:?} gets a new counter: {counter_kind:?}"); self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter_kind) } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 5fb72fcf0cf3e..ef40af3716c1f 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -7,7 +7,7 @@ mod spans; #[cfg(test)] mod tests; -use self::counters::{BcbCounter, CoverageCounters}; +use self::counters::{CounterIncrementSite, CoverageCounters}; use self::graph::{BasicCoverageBlock, CoverageGraph}; use self::spans::{BcbMapping, BcbMappingKind, CoverageSpans}; @@ -155,61 +155,52 @@ fn inject_coverage_statements<'tcx>( bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool, coverage_counters: &CoverageCounters, ) { - // Process the counters associated with BCB nodes. - for (bcb, counter_kind) in coverage_counters.bcb_node_counters() { - let do_inject = match counter_kind { - // Counter-increment statements always need to be injected. - BcbCounter::Counter { .. } => true, - // The only purpose of expression-used statements is to detect - // when a mapping is unreachable, so we only inject them for - // expressions with one or more mappings. - BcbCounter::Expression { .. } => bcb_has_coverage_spans(bcb), - }; - if do_inject { - inject_statement( - mir_body, - make_mir_coverage_kind(counter_kind), - basic_coverage_blocks[bcb].leader_bb(), - ); - } - } - - // Process the counters associated with BCB edges. - for (from_bcb, to_bcb, counter_kind) in coverage_counters.bcb_edge_counters() { - let do_inject = match counter_kind { - // Counter-increment statements always need to be injected. - BcbCounter::Counter { .. } => true, - // BCB-edge expressions never have mappings, so they never need - // a corresponding statement. - BcbCounter::Expression { .. } => false, + // Inject counter-increment statements into MIR. + for (id, counter_increment_site) in coverage_counters.counter_increment_sites() { + // Determine the block to inject a counter-increment statement into. + // For BCB nodes this is just their first block, but for edges we need + // to create a new block between the two BCBs, and inject into that. + let target_bb = match *counter_increment_site { + CounterIncrementSite::Node { bcb } => basic_coverage_blocks[bcb].leader_bb(), + CounterIncrementSite::Edge { from_bcb, to_bcb } => { + // Create a new block between the last block of `from_bcb` and + // the first block of `to_bcb`. + let from_bb = basic_coverage_blocks[from_bcb].last_bb(); + let to_bb = basic_coverage_blocks[to_bcb].leader_bb(); + + let new_bb = inject_edge_counter_basic_block(mir_body, from_bb, to_bb); + debug!( + "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \ + requires a new MIR BasicBlock {new_bb:?} for counter increment {id:?}", + ); + new_bb + } }; - if !do_inject { - continue; - } - - // We need to inject a coverage statement into a new BB between the - // last BB of `from_bcb` and the first BB of `to_bcb`. - let from_bb = basic_coverage_blocks[from_bcb].last_bb(); - let to_bb = basic_coverage_blocks[to_bcb].leader_bb(); - let new_bb = inject_edge_counter_basic_block(mir_body, from_bb, to_bb); - debug!( - "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \ - requires a new MIR BasicBlock {new_bb:?} for edge counter {counter_kind:?}", - ); - - // Inject a counter into the newly-created BB. - inject_statement(mir_body, make_mir_coverage_kind(counter_kind), new_bb); + inject_statement(mir_body, CoverageKind::CounterIncrement { id }, target_bb); } -} -fn make_mir_coverage_kind(counter_kind: &BcbCounter) -> CoverageKind { - match *counter_kind { - BcbCounter::Counter { id } => CoverageKind::CounterIncrement { id }, - BcbCounter::Expression { id } => CoverageKind::ExpressionUsed { id }, + // For each counter expression that is directly associated with at least one + // span, we inject an "expression-used" statement, so that coverage codegen + // can check whether the injected statement survived MIR optimization. + // (BCB edges can't have spans, so we only need to process BCB nodes here.) + // + // See the code in `rustc_codegen_llvm::coverageinfo::map_data` that deals + // with "expressions seen" and "zero terms". + for (bcb, expression_id) in coverage_counters + .bcb_nodes_with_coverage_expressions() + .filter(|&(bcb, _)| bcb_has_coverage_spans(bcb)) + { + inject_statement( + mir_body, + CoverageKind::ExpressionUsed { id: expression_id }, + basic_coverage_blocks[bcb].leader_bb(), + ); } } +/// Given two basic blocks that have a control-flow edge between them, creates +/// and returns a new block that sits between those blocks. fn inject_edge_counter_basic_block( mir_body: &mut mir::Body<'_>, from_bb: BasicBlock, From c9c049b2b42f4c05ec49fd1c9125fa4333badd3f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 12 Jan 2024 17:12:45 +1100 Subject: [PATCH 493/676] 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 48f664b5027f5912edbbfc240f90ed439be73280 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 1 Feb 2024 16:49:23 -0800 Subject: [PATCH 494/676] Ignore test-panic-abort tests on Android Until #120567 is fixed. --- tests/ui/test-attrs/test-panic-abort-nocapture.rs | 1 + tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr | 4 ++-- tests/ui/test-attrs/test-panic-abort.rs | 1 + tests/ui/test-attrs/test-panic-abort.run.stdout | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.rs b/tests/ui/test-attrs/test-panic-abort-nocapture.rs index af530cc1a0b8f..c7415818e10f5 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.rs +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.rs @@ -6,6 +6,7 @@ // exec-env:RUST_BACKTRACE=0 // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-android #120567 // ignore-wasm no panic or subprocess support // ignore-emscripten no panic or subprocess support // ignore-sgx no subprocess support diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr index 6997833834df6..16001b3eecd4d 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr @@ -1,9 +1,9 @@ -thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:33:5: +thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:34:5: assertion `left == right` failed left: 2 right: 4 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:27:5: +thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:28:5: assertion `left == right` failed left: 2 right: 4 diff --git a/tests/ui/test-attrs/test-panic-abort.rs b/tests/ui/test-attrs/test-panic-abort.rs index 08e5242af66f9..d80e2435614dc 100644 --- a/tests/ui/test-attrs/test-panic-abort.rs +++ b/tests/ui/test-attrs/test-panic-abort.rs @@ -6,6 +6,7 @@ // exec-env:RUST_BACKTRACE=0 // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-android #120567 // ignore-wasm no panic or subprocess support // ignore-emscripten no panic or subprocess support // ignore-sgx no subprocess support diff --git a/tests/ui/test-attrs/test-panic-abort.run.stdout b/tests/ui/test-attrs/test-panic-abort.run.stdout index 0e27f6fb655b0..f5d14e77da963 100644 --- a/tests/ui/test-attrs/test-panic-abort.run.stdout +++ b/tests/ui/test-attrs/test-panic-abort.run.stdout @@ -17,7 +17,7 @@ hello, world testing123 ---- it_fails stderr ---- testing321 -thread 'main' panicked at $DIR/test-panic-abort.rs:38:5: +thread 'main' panicked at $DIR/test-panic-abort.rs:39:5: assertion `left == right` failed left: 2 right: 5 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 495/676] 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 496/676] 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 497/676] 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 498/676] 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 499/676] 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 500/676] 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 501/676] 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 502/676] 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 503/676] 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 504/676] 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 505/676] 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 506/676] 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 507/676] 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 0e16885abd6997897a28627d1ff514c106261a7f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jan 2024 21:48:54 +0000 Subject: [PATCH 508/676] Use deeply_normalize_with_skipped_universes in when processing type outlives --- compiler/rustc_trait_selection/src/regions.rs | 3 ++- .../traits/next-solver/normalize-region-obligations.rs | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index e8929f114e165..e5a7b27446b4a 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -24,12 +24,13 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { let ty = self.resolve_vars_if_possible(ty); if self.next_trait_solver() { - crate::solve::deeply_normalize( + crate::solve::deeply_normalize_with_skipped_universes( self.at( &ObligationCause::dummy_with_span(origin.span()), outlives_env.param_env, ), ty, + vec![None; ty.outer_exclusive_binder().as_usize()], ) .map_err(|_| ty) } else { diff --git a/tests/ui/traits/next-solver/normalize-region-obligations.rs b/tests/ui/traits/next-solver/normalize-region-obligations.rs index 13c86b630f60e..d189e4893a320 100644 --- a/tests/ui/traits/next-solver/normalize-region-obligations.rs +++ b/tests/ui/traits/next-solver/normalize-region-obligations.rs @@ -1,4 +1,4 @@ -// revisions: normalize_param_env normalize_obligation +// revisions: normalize_param_env normalize_obligation hrtb // check-pass // compile-flags: -Znext-solver @@ -7,16 +7,23 @@ trait Foo { type Gat<'a> where ::Assoc: 'a; #[cfg(normalize_obligation)] type Gat<'a> where Self: 'a; + #[cfg(hrtb)] + type Gat<'b> where for<'a> >::Assoc: 'b; } trait Mirror { type Assoc: ?Sized; } impl Mirror for T { type Assoc = T; } +trait MirrorRegion<'a> { type Assoc: ?Sized; } +impl<'a, T> MirrorRegion<'a> for T { type Assoc = T; } + impl Foo for T { #[cfg(normalize_param_env)] type Gat<'a> = i32 where T: 'a; #[cfg(normalize_obligation)] type Gat<'a> = i32 where ::Assoc: 'a; + #[cfg(hrtb)] + type Gat<'b> = i32 where Self: 'b; } fn main() {} From 7576b77e50f2f8a4f256876dd38563e5e5becdee Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jan 2024 21:49:55 +0000 Subject: [PATCH 509/676] Do process_registered_region_obligations in a loop --- .../src/infer/outlives/obligations.rs | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index b10bf98e8b50a..cf68a60e280d1 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -153,22 +153,28 @@ impl<'tcx> InferCtxt<'tcx> { .try_collect() .map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?; - let my_region_obligations = self.take_registered_region_obligations(); - - for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { - let sup_type = - deeply_normalize_ty(sup_type, origin.clone()).map_err(|e| (e, origin.clone()))?; - debug!(?sup_type, ?sub_region, ?origin); - - let outlives = &mut TypeOutlives::new( - self, - self.tcx, - outlives_env.region_bound_pairs(), - None, - &normalized_caller_bounds, - ); - let category = origin.to_constraint_category(); - outlives.type_must_outlive(origin, sup_type, sub_region, category); + // Must loop since the process of normalizing may itself register region obligations. + loop { + let my_region_obligations = self.take_registered_region_obligations(); + if my_region_obligations.is_empty() { + break; + } + + for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { + let sup_type = deeply_normalize_ty(sup_type, origin.clone()) + .map_err(|e| (e, origin.clone()))?; + debug!(?sup_type, ?sub_region, ?origin); + + let outlives = &mut TypeOutlives::new( + self, + self.tcx, + outlives_env.region_bound_pairs(), + None, + &normalized_caller_bounds, + ); + let category = origin.to_constraint_category(); + outlives.type_must_outlive(origin, sup_type, sub_region, category); + } } Ok(()) From 7d1fda7b40b580e5d8c7de1e3bfef7e35e997cee Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jan 2024 21:50:05 +0000 Subject: [PATCH 510/676] Normalize type outlives obligations in NLL --- .../src/type_check/constraint_conversion.rs | 97 +++++++++++++++---- .../src/type_check/free_region_relations.rs | 72 +++++++++----- compiler/rustc_borrowck/src/type_check/mod.rs | 6 +- .../normalize-type-outlives-in-param-env.rs | 18 ++++ .../next-solver/normalize-type-outlives.rs | 13 +++ 5 files changed, 156 insertions(+), 50 deletions(-) create mode 100644 tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs create mode 100644 tests/ui/traits/next-solver/normalize-type-outlives.rs diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 52559f9039b65..71035eea5d175 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -5,10 +5,15 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::solve::deeply_normalize; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; +use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; +use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use crate::{ constraints::OutlivesConstraint, @@ -33,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { /// our special inference variable there, we would mess that up. region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, + param_env: ty::ParamEnv<'tcx>, known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, @@ -47,6 +53,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, + param_env: ty::ParamEnv<'tcx>, known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, @@ -59,6 +66,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { universal_regions, region_bound_pairs, implicit_region_bound, + param_env, known_type_outlives_obligations, locations, span, @@ -137,36 +145,83 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // Extract out various useful fields we'll need below. let ConstraintConversion { tcx, + infcx, + param_env, region_bound_pairs, implicit_region_bound, known_type_outlives_obligations, .. } = *self; - let ty::OutlivesPredicate(k1, r2) = predicate; - match k1.unpack() { - GenericArgKind::Lifetime(r1) => { - let r1_vid = self.to_region_vid(r1); - let r2_vid = self.to_region_vid(r2); - self.add_outlives(r1_vid, r2_vid, constraint_category); - } + let mut outlives_predicates = vec![(predicate, constraint_category)]; + while let Some((ty::OutlivesPredicate(k1, r2), constraint_category)) = + outlives_predicates.pop() + { + match k1.unpack() { + GenericArgKind::Lifetime(r1) => { + let r1_vid = self.to_region_vid(r1); + let r2_vid = self.to_region_vid(r2); + self.add_outlives(r1_vid, r2_vid, constraint_category); + } - GenericArgKind::Type(t1) => { - // we don't actually use this for anything, but - // the `TypeOutlives` code needs an origin. - let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + GenericArgKind::Type(mut t1) => { + // Normalize the type we receive from a `TypeOutlives` obligation + // in the new trait solver. + if infcx.next_trait_solver() { + let result = CustomTypeOp::new( + |ocx| { + match deeply_normalize( + ocx.infcx.at( + &ObligationCause::dummy_with_span(self.span), + param_env, + ), + t1, + ) { + Ok(normalized_ty) => { + t1 = normalized_ty; + } + Err(e) => { + infcx.err_ctxt().report_fulfillment_errors(e); + } + } - TypeOutlives::new( - &mut *self, - tcx, - region_bound_pairs, - Some(implicit_region_bound), - known_type_outlives_obligations, - ) - .type_must_outlive(origin, t1, r2, constraint_category); - } + Ok(()) + }, + "normalize type outlives obligation", + ) + .fully_perform(infcx, self.span); + + match result { + Ok(TypeOpOutput { output: (), constraints, .. }) => { + if let Some(constraints) = constraints { + assert!( + constraints.member_constraints.is_empty(), + "FIXME(-Znext-solver): How do I handle these?" + ); + outlives_predicates + .extend(constraints.outlives.iter().copied()); + } + } + Err(_) => {} + } + } - GenericArgKind::Const(_) => unreachable!(), + // we don't actually use this for anything, but + // the `TypeOutlives` code needs an origin. + let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + + TypeOutlives::new( + &mut *self, + tcx, + region_bound_pairs, + Some(implicit_region_bound), + known_type_outlives_obligations, + ) + .type_must_outlive(origin, t1, r2, constraint_category); + } + + GenericArgKind::Const(_) => unreachable!(), + } } } diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index d518f54fd2533..4d53a53ee197b 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -8,8 +8,11 @@ use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::InferCtxt; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::OutlivesBound; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; -use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, DUMMY_SP}; +use rustc_trait_selection::solve::deeply_normalize_with_skipped_universes; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; use type_op::TypeOpOutput; @@ -52,7 +55,6 @@ pub(crate) struct CreateResult<'tcx> { pub(crate) fn create<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, universal_regions: &Rc>, constraints: &mut MirTypeckRegionConstraints<'tcx>, @@ -60,7 +62,6 @@ pub(crate) fn create<'tcx>( UniversalRegionRelationsBuilder { infcx, param_env, - known_type_outlives_obligations, implicit_region_bound, constraints, universal_regions: universal_regions.clone(), @@ -178,7 +179,6 @@ impl UniversalRegionRelations<'_> { struct UniversalRegionRelationsBuilder<'this, 'tcx> { infcx: &'this InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], universal_regions: Rc>, implicit_region_bound: ty::Region<'tcx>, constraints: &'this mut MirTypeckRegionConstraints<'tcx>, @@ -222,6 +222,35 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { self.relate_universal_regions(fr, fr_fn_body); } + // Normalize the assumptions we use to borrowck the program. + let mut constraints = vec![]; + let mut known_type_outlives_obligations = vec![]; + for bound in param_env.caller_bounds() { + let Some(outlives) = bound.as_type_outlives_clause() else { continue }; + let ty::OutlivesPredicate(mut ty, region) = outlives.skip_binder(); + + // In the new solver, normalize the type-outlives obligation assumptions. + if self.infcx.next_trait_solver() { + match deeply_normalize_with_skipped_universes( + self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env), + ty, + vec![None; ty.outer_exclusive_binder().as_usize()], + ) { + Ok(normalized_ty) => { + ty = normalized_ty; + } + Err(e) => { + self.infcx.err_ctxt().report_fulfillment_errors(e); + } + } + } + + known_type_outlives_obligations + .push(outlives.rebind(ty::OutlivesPredicate(ty, region))); + } + let known_type_outlives_obligations = + self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations); + let unnormalized_input_output_tys = self .universal_regions .unnormalized_input_tys @@ -239,7 +268,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // the `relations` is built. let mut normalized_inputs_and_output = Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1); - let mut constraints = vec![]; for ty in unnormalized_input_output_tys { debug!("build: input_or_output={:?}", ty); // We add implied bounds from both the unnormalized and normalized ty. @@ -304,7 +332,19 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { } for c in constraints { - self.push_region_constraints(c, span); + constraint_conversion::ConstraintConversion::new( + self.infcx, + &self.universal_regions, + &self.region_bound_pairs, + self.implicit_region_bound, + param_env, + known_type_outlives_obligations, + Locations::All(span), + span, + ConstraintCategory::Internal, + self.constraints, + ) + .convert_all(c); } CreateResult { @@ -313,30 +353,12 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { outlives: self.outlives.freeze(), inverse_outlives: self.inverse_outlives.freeze(), }), - known_type_outlives_obligations: self.known_type_outlives_obligations, + known_type_outlives_obligations, region_bound_pairs: self.region_bound_pairs, normalized_inputs_and_output, } } - #[instrument(skip(self, data), level = "debug")] - fn push_region_constraints(&mut self, data: &QueryRegionConstraints<'tcx>, span: Span) { - debug!("constraints generated: {:#?}", data); - - constraint_conversion::ConstraintConversion::new( - self.infcx, - &self.universal_regions, - &self.region_bound_pairs, - self.implicit_region_bound, - self.known_type_outlives_obligations, - Locations::All(span), - span, - ConstraintCategory::Internal, - self.constraints, - ) - .convert_all(data); - } - /// Update the type of a single local, which should represent /// either the return type of the MIR or one of its arguments. At /// the same time, compute and add any implied bounds that come diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 59c4d9a6c78ca..c65173baea57f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -156,10 +156,6 @@ pub(crate) fn type_check<'mir, 'tcx>( } = free_region_relations::create( infcx, param_env, - // FIXME(-Znext-solver): These are unnormalized. Normalize them. - infcx.tcx.arena.alloc_from_iter( - param_env.caller_bounds().iter().filter_map(|clause| clause.as_type_outlives_clause()), - ), implicit_region_bound, universal_regions, &mut constraints, @@ -1136,6 +1132,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, + self.param_env, self.known_type_outlives_obligations, locations, locations.span(self.body), @@ -2740,6 +2737,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, + self.param_env, self.known_type_outlives_obligations, locations, DUMMY_SP, // irrelevant; will be overridden. diff --git a/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs b/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs new file mode 100644 index 0000000000000..7477c56cd5487 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs @@ -0,0 +1,18 @@ +// check-pass +// compile-flags: -Znext-solver + +trait Mirror { + type Assoc; +} + +impl Mirror for T { + type Assoc = T; +} + +fn is_static() {} + +fn test() where ::Assoc: 'static { + is_static::(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-type-outlives.rs b/tests/ui/traits/next-solver/normalize-type-outlives.rs new file mode 100644 index 0000000000000..f50eb6326e239 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-type-outlives.rs @@ -0,0 +1,13 @@ +// check-pass + +trait Tr<'a> { + type Assoc; +} + +fn outlives<'o, T: 'o>() {} + +fn foo<'a, 'b, T: Tr<'a, Assoc = ()>>() { + outlives::<'b, T::Assoc>(); +} + +fn main() {} From a371059933c11c79f9583ec149d56774e87b940f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 1 Feb 2024 18:04:16 +0000 Subject: [PATCH 511/676] Don't hang when there's an infinite loop of outlives obligations --- .../src/type_check/constraint_conversion.rs | 133 ++++++++++-------- .../src/infer/outlives/obligations.rs | 8 +- 2 files changed, 83 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 71035eea5d175..4c224248945b3 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -154,74 +154,93 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } = *self; let mut outlives_predicates = vec![(predicate, constraint_category)]; - while let Some((ty::OutlivesPredicate(k1, r2), constraint_category)) = - outlives_predicates.pop() - { - match k1.unpack() { - GenericArgKind::Lifetime(r1) => { - let r1_vid = self.to_region_vid(r1); - let r2_vid = self.to_region_vid(r2); - self.add_outlives(r1_vid, r2_vid, constraint_category); - } + for iteration in 0.. { + if outlives_predicates.is_empty() { + break; + } - GenericArgKind::Type(mut t1) => { - // Normalize the type we receive from a `TypeOutlives` obligation - // in the new trait solver. - if infcx.next_trait_solver() { - let result = CustomTypeOp::new( - |ocx| { - match deeply_normalize( - ocx.infcx.at( - &ObligationCause::dummy_with_span(self.span), - param_env, - ), - t1, - ) { - Ok(normalized_ty) => { - t1 = normalized_ty; - } - Err(e) => { - infcx.err_ctxt().report_fulfillment_errors(e); + if !self.tcx.recursion_limit().value_within_limit(iteration) { + bug!( + "FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}" + ); + } + + let mut next_outlives_predicates = vec![]; + for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates { + match k1.unpack() { + GenericArgKind::Lifetime(r1) => { + let r1_vid = self.to_region_vid(r1); + let r2_vid = self.to_region_vid(r2); + self.add_outlives(r1_vid, r2_vid, constraint_category); + } + + GenericArgKind::Type(mut t1) => { + // Normalize the type we receive from a `TypeOutlives` obligation + // in the new trait solver. + if infcx.next_trait_solver() { + let result = CustomTypeOp::new( + |ocx| { + match deeply_normalize( + ocx.infcx.at( + &ObligationCause::dummy_with_span(self.span), + param_env, + ), + t1, + ) { + Ok(normalized_ty) => { + t1 = normalized_ty; + } + Err(e) => { + infcx.err_ctxt().report_fulfillment_errors(e); + } } - } - Ok(()) - }, - "normalize type outlives obligation", - ) - .fully_perform(infcx, self.span); + Ok(()) + }, + "normalize type outlives obligation", + ) + .fully_perform(infcx, self.span); - match result { - Ok(TypeOpOutput { output: (), constraints, .. }) => { - if let Some(constraints) = constraints { - assert!( - constraints.member_constraints.is_empty(), - "FIXME(-Znext-solver): How do I handle these?" - ); - outlives_predicates - .extend(constraints.outlives.iter().copied()); + match result { + Ok(TypeOpOutput { output: (), constraints, .. }) => { + if let Some(constraints) = constraints { + assert!( + constraints.member_constraints.is_empty(), + "no member constraints expected from normalizing: {:#?}", + constraints.member_constraints + ); + next_outlives_predicates + .extend(constraints.outlives.iter().copied()); + } } + Err(_) => {} } - Err(_) => {} } - } - // we don't actually use this for anything, but - // the `TypeOutlives` code needs an origin. - let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + // we don't actually use this for anything, but + // the `TypeOutlives` code needs an origin. + let origin = infer::RelateParamBound(DUMMY_SP, t1, None); - TypeOutlives::new( - &mut *self, - tcx, - region_bound_pairs, - Some(implicit_region_bound), - known_type_outlives_obligations, - ) - .type_must_outlive(origin, t1, r2, constraint_category); - } + TypeOutlives::new( + &mut *self, + tcx, + region_bound_pairs, + Some(implicit_region_bound), + known_type_outlives_obligations, + ) + .type_must_outlive( + origin, + t1, + r2, + constraint_category, + ); + } - GenericArgKind::Const(_) => unreachable!(), + GenericArgKind::Const(_) => unreachable!(), + } } + + outlives_predicates = next_outlives_predicates; } } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index cf68a60e280d1..c36d8556d17dd 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -154,12 +154,18 @@ impl<'tcx> InferCtxt<'tcx> { .map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?; // Must loop since the process of normalizing may itself register region obligations. - loop { + for iteration in 0.. { let my_region_obligations = self.take_registered_region_obligations(); if my_region_obligations.is_empty() { break; } + if !self.tcx.recursion_limit().value_within_limit(iteration) { + bug!( + "FIXME(-Znext-solver): Overflowed when processing region obligations: {my_region_obligations:#?}" + ); + } + for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { let sup_type = deeply_normalize_ty(sup_type, origin.clone()) .map_err(|e| (e, origin.clone()))?; From e951bcff96ac606aad3b7870c7fa64a4a48aa04b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Feb 2024 18:31:35 +0000 Subject: [PATCH 512/676] Normalize the whole PolyTypeOutlivesPredicate, more simplifications --- .../src/type_check/constraint_conversion.rs | 84 +++++++++---------- .../src/type_check/free_region_relations.rs | 17 ++-- .../src/infer/error_reporting/mod.rs | 7 +- .../src/infer/lexical_region_resolve/mod.rs | 2 +- .../rustc_infer/src/infer/outlives/mod.rs | 13 +-- .../src/infer/outlives/obligations.rs | 38 +++++---- compiler/rustc_trait_selection/src/regions.rs | 6 +- .../src/traits/auto_trait.rs | 2 +- .../next-solver/specialization-transmute.rs | 2 +- .../specialization-transmute.stderr | 2 +- 10 files changed, 92 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 4c224248945b3..c97e31701669c 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -5,13 +5,11 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; +use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::GenericArgKind; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::solve::deeply_normalize; -use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; @@ -146,7 +144,6 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { let ConstraintConversion { tcx, infcx, - param_env, region_bound_pairs, implicit_region_bound, known_type_outlives_obligations, @@ -178,43 +175,10 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // Normalize the type we receive from a `TypeOutlives` obligation // in the new trait solver. if infcx.next_trait_solver() { - let result = CustomTypeOp::new( - |ocx| { - match deeply_normalize( - ocx.infcx.at( - &ObligationCause::dummy_with_span(self.span), - param_env, - ), - t1, - ) { - Ok(normalized_ty) => { - t1 = normalized_ty; - } - Err(e) => { - infcx.err_ctxt().report_fulfillment_errors(e); - } - } - - Ok(()) - }, - "normalize type outlives obligation", - ) - .fully_perform(infcx, self.span); - - match result { - Ok(TypeOpOutput { output: (), constraints, .. }) => { - if let Some(constraints) = constraints { - assert!( - constraints.member_constraints.is_empty(), - "no member constraints expected from normalizing: {:#?}", - constraints.member_constraints - ); - next_outlives_predicates - .extend(constraints.outlives.iter().copied()); - } - } - Err(_) => {} - } + t1 = self.normalize_and_add_type_outlives_constraints( + t1, + &mut next_outlives_predicates, + ); } // we don't actually use this for anything, but @@ -306,6 +270,42 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { debug!("add_type_test(type_test={:?})", type_test); self.constraints.type_tests.push(type_test); } + + fn normalize_and_add_type_outlives_constraints( + &self, + ty: Ty<'tcx>, + next_outlives_predicates: &mut Vec<( + ty::OutlivesPredicate, ty::Region<'tcx>>, + ConstraintCategory<'tcx>, + )>, + ) -> Ty<'tcx> { + let result = CustomTypeOp::new( + |ocx| { + deeply_normalize( + ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env), + ty, + ) + .map_err(|_| NoSolution) + }, + "normalize type outlives obligation", + ) + .fully_perform(self.infcx, self.span); + + match result { + Ok(TypeOpOutput { output: ty, constraints, .. }) => { + if let Some(constraints) = constraints { + assert!( + constraints.member_constraints.is_empty(), + "no member constraints expected from normalizing: {:#?}", + constraints.member_constraints + ); + next_outlives_predicates.extend(constraints.outlives.iter().copied()); + } + ty + } + Err(_) => ty, + } + } } impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> { diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 4d53a53ee197b..2e0caf4481902 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -11,7 +11,7 @@ use rustc_middle::traits::query::OutlivesBound; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, DUMMY_SP}; -use rustc_trait_selection::solve::deeply_normalize_with_skipped_universes; +use rustc_trait_selection::solve::deeply_normalize; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; @@ -226,18 +226,16 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let mut constraints = vec![]; let mut known_type_outlives_obligations = vec![]; for bound in param_env.caller_bounds() { - let Some(outlives) = bound.as_type_outlives_clause() else { continue }; - let ty::OutlivesPredicate(mut ty, region) = outlives.skip_binder(); + let Some(mut outlives) = bound.as_type_outlives_clause() else { continue }; // In the new solver, normalize the type-outlives obligation assumptions. if self.infcx.next_trait_solver() { - match deeply_normalize_with_skipped_universes( + match deeply_normalize( self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env), - ty, - vec![None; ty.outer_exclusive_binder().as_usize()], + outlives, ) { - Ok(normalized_ty) => { - ty = normalized_ty; + Ok(normalized_outlives) => { + outlives = normalized_outlives; } Err(e) => { self.infcx.err_ctxt().report_fulfillment_errors(e); @@ -245,8 +243,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { } } - known_type_outlives_obligations - .push(outlives.rebind(ty::OutlivesPredicate(ty, region))); + known_type_outlives_obligations.push(outlives); } let known_type_outlives_obligations = self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b8344310d5dfd..f74e13db44795 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -71,6 +71,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError}; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; +use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{ self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -519,10 +520,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit(); } - RegionResolutionError::CannotNormalize(ty, origin) => { + RegionResolutionError::CannotNormalize(clause, origin) => { + let clause: ty::Clause<'tcx> = + clause.map_bound(ty::ClauseKind::TypeOutlives).to_predicate(self.tcx); self.tcx .dcx() - .struct_span_err(origin.span(), format!("cannot normalize `{ty}`")) + .struct_span_err(origin.span(), format!("cannot normalize `{clause}`")) .emit(); } } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 4a1169e68e087..6137506d4a994 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -99,7 +99,7 @@ pub enum RegionResolutionError<'tcx> { Region<'tcx>, // the placeholder `'b` ), - CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>), + CannotNormalize(ty::PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>), } impl<'tcx> RegionResolutionError<'tcx> { diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 926e198b21915..a4f9316b5020f 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -4,8 +4,8 @@ use super::region_constraints::RegionConstraintData; use super::{InferCtxt, RegionResolutionError, SubregionOrigin}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; -use rustc_middle::traits::query::OutlivesBound; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::traits::query::{NoSolution, OutlivesBound}; +use rustc_middle::ty; pub mod components; pub mod env; @@ -49,12 +49,15 @@ impl<'tcx> InferCtxt<'tcx> { pub fn resolve_regions_with_normalize( &self, outlives_env: &OutlivesEnvironment<'tcx>, - deeply_normalize_ty: impl Fn(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result, Ty<'tcx>>, + deeply_normalize_ty: impl Fn( + ty::PolyTypeOutlivesPredicate<'tcx>, + SubregionOrigin<'tcx>, + ) -> Result, NoSolution>, ) -> Vec> { match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) { Ok(()) => {} - Err((ty, origin)) => { - return vec![RegionResolutionError::CannotNormalize(ty, origin)]; + Err((clause, origin)) => { + return vec![RegionResolutionError::CannotNormalize(clause, origin)]; } }; diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index c36d8556d17dd..7208f17fb340f 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,8 +68,9 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::GenericArgKind; +use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate}; use rustc_span::DUMMY_SP; use smallvec::smallvec; @@ -125,11 +126,15 @@ impl<'tcx> InferCtxt<'tcx> { /// invoked after all type-inference variables have been bound -- /// right before lexical region resolution. #[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))] - pub fn process_registered_region_obligations( + pub fn process_registered_region_obligations( &self, outlives_env: &OutlivesEnvironment<'tcx>, - mut deeply_normalize_ty: impl FnMut(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result, E>, - ) -> Result<(), (E, SubregionOrigin<'tcx>)> { + mut deeply_normalize_ty: impl FnMut( + PolyTypeOutlivesPredicate<'tcx>, + SubregionOrigin<'tcx>, + ) + -> Result, NoSolution>, + ) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); let normalized_caller_bounds: Vec<_> = outlives_env @@ -137,21 +142,19 @@ impl<'tcx> InferCtxt<'tcx> { .caller_bounds() .iter() .filter_map(|clause| { - let bound_clause = clause.kind(); - let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else { - return None; - }; + let outlives = clause.as_type_outlives_clause()?; Some( deeply_normalize_ty( - outlives.0, + outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP), ) - .map(|ty| bound_clause.rebind(ty::OutlivesPredicate(ty, outlives.1))), + // FIXME(-Znext-solver): How do we accurately report an error span here :( + .map_err(|NoSolution| { + (outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)) + }), ) }) - // FIXME(-Znext-solver): How do we accurately report an error here :( - .try_collect() - .map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?; + .try_collect()?; // Must loop since the process of normalizing may itself register region obligations. for iteration in 0.. { @@ -167,8 +170,13 @@ impl<'tcx> InferCtxt<'tcx> { } for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { - let sup_type = deeply_normalize_ty(sup_type, origin.clone()) - .map_err(|e| (e, origin.clone()))?; + let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region)); + let ty::OutlivesPredicate(sup_type, sub_region) = + deeply_normalize_ty(outlives, origin.clone()) + .map_err(|NoSolution| (outlives, origin.clone()))? + .no_bound_vars() + .expect("started with no bound vars, should end with no bound vars"); + debug!(?sup_type, ?sub_region, ?origin); let outlives = &mut TypeOutlives::new( diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index e5a7b27446b4a..756db7cc2063f 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -1,5 +1,6 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, RegionResolutionError}; +use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; pub trait InferCtxtRegionExt<'tcx> { @@ -24,15 +25,14 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { let ty = self.resolve_vars_if_possible(ty); if self.next_trait_solver() { - crate::solve::deeply_normalize_with_skipped_universes( + crate::solve::deeply_normalize( self.at( &ObligationCause::dummy_with_span(origin.span()), outlives_env.param_env, ), ty, - vec![None; ty.outer_exclusive_binder().as_usize()], ) - .map_err(|_| ty) + .map_err(|_| NoSolution) } else { Ok(ty) } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 7933654a91546..81c72fc4b7b03 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } let outlives_env = OutlivesEnvironment::new(full_env); - let _ = infcx.process_registered_region_obligations::(&outlives_env, |ty, _| Ok(ty)); + let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty)); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index e7de564877d09..a0855dd1e1714 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -1,5 +1,5 @@ // compile-flags: -Znext-solver -//~^ ERROR cannot normalize `::Id` +//~^ ERROR cannot normalize `::Id: '_` #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index a1cf5b761e34f..3100a92e3eb4d 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -8,7 +8,7 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error: cannot normalize `::Id` +error: cannot normalize `::Id: '_` error[E0282]: type annotations needed --> $DIR/specialization-transmute.rs:14:23 From 61d1ebe50be6343a3d5ee22db486163ff47e9ff1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Feb 2024 20:12:37 +0100 Subject: [PATCH 513/676] 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 514/676] 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 515/676] 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 516/676] 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 517/676] `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 518/676] `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 519/676] 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 520/676] 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 521/676] 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 522/676] 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 523/676] 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 524/676] 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 6b2a8249c196898c3932d818b263f4c32a5ed454 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Feb 2024 22:45:25 +0000 Subject: [PATCH 525/676] Remove dead args from functions --- compiler/rustc_borrowck/src/nll.rs | 2 +- .../rustc_borrowck/src/region_infer/mod.rs | 41 +------------------ compiler/rustc_borrowck/src/type_check/mod.rs | 1 - .../rustc_hir_analysis/src/astconv/bounds.rs | 2 - .../src/astconv/generics.rs | 16 +------- .../rustc_hir_analysis/src/astconv/mod.rs | 10 ++--- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 12 ++---- compiler/rustc_hir_typeck/src/lib.rs | 2 +- .../src/mem_categorization.rs | 3 +- .../rustc_hir_typeck/src/method/confirm.rs | 1 - compiler/rustc_infer/src/infer/mod.rs | 6 +-- .../rustc_infer/src/infer/opaque_types.rs | 1 - .../rustc_infer/src/infer/relate/combine.rs | 5 +-- compiler/rustc_middle/src/thir.rs | 1 - compiler/rustc_middle/src/ty/_match.rs | 2 +- .../src/const_prop_lint.rs | 9 +--- compiler/rustc_pattern_analysis/src/lints.rs | 2 +- .../rustc_query_system/src/dep_graph/graph.rs | 5 +-- compiler/rustc_resolve/src/late.rs | 9 ++-- .../src/solve/assembly/mod.rs | 2 +- .../rustc_trait_selection/src/solve/mod.rs | 19 --------- .../src/traits/select/mod.rs | 5 +-- 22 files changed, 32 insertions(+), 124 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index cc8208e9dc306..6a04af4506b8d 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -184,7 +184,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let (closure_region_requirements, nll_errors) = - regioncx.solve(infcx, param_env, body, polonius_output.clone()); + regioncx.solve(infcx, body, polonius_output.clone()); if !nll_errors.is_empty() { // Suppress unhelpful extra errors in `infer_opaque_types`. diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 89b203f80a435..3153b709ffe38 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -658,7 +658,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(super) fn solve( &mut self, infcx: &InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, polonius_output: Option>, ) -> (Option>, RegionErrors<'tcx>) { @@ -674,7 +673,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // eagerly. let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer); + self.check_type_tests(infcx, outlives_requirements.as_mut(), &mut errors_buffer); debug!(?errors_buffer); debug!(?outlives_requirements); @@ -932,7 +931,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn check_type_tests( &self, infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, mut propagated_outlives_requirements: Option<&mut Vec>>, errors_buffer: &mut RegionErrors<'tcx>, ) { @@ -957,12 +955,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements { - if self.try_promote_type_test( - infcx, - body, - type_test, - propagated_outlives_requirements, - ) { + if self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements) { continue; } } @@ -1016,7 +1009,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn try_promote_type_test( &self, infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, type_test: &TypeTest<'tcx>, propagated_outlives_requirements: &mut Vec>, ) -> bool { @@ -1179,35 +1171,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty))) } - /// Returns a universally quantified region that outlives the - /// value of `r` (`r` may be existentially or universally - /// quantified). - /// - /// Since `r` is (potentially) an existential region, it has some - /// value which may include (a) any number of points in the CFG - /// and (b) any number of `end('x)` elements of universally - /// quantified regions. To convert this into a single universal - /// region we do as follows: - /// - /// - Ignore the CFG points in `'r`. All universally quantified regions - /// include the CFG anyhow. - /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding - /// a result `'y`. - #[instrument(skip(self), level = "debug", ret)] - pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid { - debug!(r = %self.region_value_str(r)); - - // Find the smallest universal region that contains all other - // universal regions within `region`. - let mut lub = self.universal_regions.fr_fn_body; - let r_scc = self.constraint_sccs.scc(r); - for ur in self.scc_values.universal_regions_outlived_by(r_scc) { - lub = self.universal_region_relations.postdom_upper_bound(lub, ur); - } - - lub - } - /// Like `universal_upper_bound`, but returns an approximation more suitable /// for diagnostics. If `r` contains multiple disjoint universal regions /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 59c4d9a6c78ca..64cdc2983ca40 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -217,7 +217,6 @@ pub(crate) fn type_check<'mir, 'tcx>( CustomTypeOp::new( |ocx| { ocx.infcx.register_member_constraints( - param_env, opaque_type_key, decl.hidden_type.ty, decl.hidden_type.span, diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index c22daad334fc5..46266058ff508 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -235,9 +235,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { speculative: bool, dup_bindings: &mut FxHashMap, path_span: Span, - constness: ty::BoundConstness, only_self_bounds: OnlySelfBounds, - polarity: ty::ImplPolarity, ) -> Result<(), ErrorGuaranteed> { // Given something like `U: SomeTrait`, we want to produce a // predicate like `::T = X`. This is somewhat diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 30b10446afcc9..aa826c1f26805 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt, }; use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS; -use rustc_span::{symbol::kw, Span}; +use rustc_span::symbol::kw; use smallvec::SmallVec; /// Report an error that a generic argument did not match the generic parameter that was @@ -404,7 +404,6 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>( /// Used specifically for function calls. pub fn check_generic_arg_count_for_call( tcx: TyCtxt<'_>, - span: Span, def_id: DefId, generics: &ty::Generics, seg: &hir::PathSegment<'_>, @@ -418,17 +417,7 @@ pub fn check_generic_arg_count_for_call( }; let has_self = generics.parent.is_none() && generics.has_self; - check_generic_arg_count( - tcx, - span, - def_id, - seg, - generics, - gen_args, - gen_pos, - has_self, - seg.infer_args, - ) + check_generic_arg_count(tcx, def_id, seg, generics, gen_args, gen_pos, has_self, seg.infer_args) } /// Checks that the correct number of generic arguments have been provided. @@ -436,7 +425,6 @@ pub fn check_generic_arg_count_for_call( #[instrument(skip(tcx, gen_pos), level = "debug")] pub(crate) fn check_generic_arg_count( tcx: TyCtxt<'_>, - span: Span, def_id: DefId, seg: &hir::PathSegment<'_>, gen_params: &ty::Generics, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 89f39897ea874..69a70557393fd 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -25,7 +25,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; -use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; +use rustc_hir::{GenericArg, GenericArgs}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; @@ -379,7 +379,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut arg_count = check_generic_arg_count( tcx, - span, def_id, seg, generics, @@ -773,9 +772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { speculative, &mut dup_bindings, binding.span, - constness, only_self_bounds, - polarity, ); // Okay to ignore `Err` because of `ErrorGuaranteed` (see above). } @@ -2491,7 +2488,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let opaque_ty = tcx.hir().item(item_id); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(&hir::OpaqueTy { origin, .. }) => { + hir::ItemKind::OpaqueTy(&hir::OpaqueTy { .. }) => { let local_def_id = item_id.owner_id.def_id; // If this is an RPITIT and we are using the new RPITIT lowering scheme, we // generate the def_id of an associated type for the trait and return as @@ -2501,7 +2498,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { local_def_id.to_def_id() }; - self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait) + self.impl_trait_ty_to_ty(def_id, lifetimes, in_trait) } ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } @@ -2571,7 +2568,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, def_id: DefId, lifetimes: &[hir::GenericArg<'_>], - origin: OpaqueTyOrigin, in_trait: bool, ) -> Ty<'tcx> { debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 60eb40bd8fe66..73b3ccf449c79 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -521,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// We must not attempt to select obligations after this method has run, or risk query cycle /// ICE. #[instrument(level = "debug", skip(self))] - pub(in super::super) fn resolve_coroutine_interiors(&self, def_id: DefId) { + pub(in super::super) fn resolve_coroutine_interiors(&self) { // Try selecting all obligations that are not blocked on inference variables. // Once we start unifying coroutine witnesses, trying to select obligations on them will // trigger query cycle ICEs, as doing so requires MIR. @@ -1175,14 +1175,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // parameter internally, but we don't allow users to specify the // parameter's value explicitly, so we have to do some error- // checking here. - let arg_count = check_generic_arg_count_for_call( - tcx, - span, - def_id, - generics, - seg, - IsMethodCall::No, - ); + let arg_count = + check_generic_arg_count_for_call(tcx, def_id, generics, seg, IsMethodCall::No); if let ExplicitLateBound::Yes = arg_count.explicit_late_bound { explicit_late_bound = ExplicitLateBound::Yes; diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index deb3ad2edc740..7aa8010f17620 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -286,7 +286,7 @@ fn typeck_with_fallback<'tcx>( debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations()); // This must be the last thing before `report_ambiguity_errors`. - fcx.resolve_coroutine_interiors(def_id.to_def_id()); + fcx.resolve_coroutine_interiors(); debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations()); diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 1ce0240f7b830..f9297550c573c 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -436,7 +436,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { pub(crate) fn cat_rvalue( &self, hir_id: hir::HirId, - span: Span, + // FIXME: remove + _span: Span, expr_ty: Ty<'tcx>, ) -> PlaceWithHirId<'tcx> { PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new()) diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 6f18cc51b11c1..38a63b6dd4302 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -356,7 +356,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let arg_count_correct = check_generic_arg_count_for_call( self.tcx, - self.span, pick.item.def_id, generics, seg, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0a39fe007fd22..432d4c0fc6255 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -862,7 +862,7 @@ impl<'tcx> InferCtxt<'tcx> { } #[instrument(skip(self, snapshot), level = "debug")] - fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'tcx>) { + fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) { let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot; self.universe.set(universe); @@ -894,7 +894,7 @@ impl<'tcx> InferCtxt<'tcx> { self.commit_from(snapshot); } Err(_) => { - self.rollback_to("commit_if_ok -- error", snapshot); + self.rollback_to(snapshot); } } r @@ -908,7 +908,7 @@ impl<'tcx> InferCtxt<'tcx> { { let snapshot = self.start_snapshot(); let r = f(&snapshot); - self.rollback_to("probe", snapshot); + self.rollback_to(snapshot); r } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index db46b39ce25fc..757ba3b1b3678 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -327,7 +327,6 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn register_member_constraints( &self, - param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, concrete_ty: Ty<'tcx>, span: Span, diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 1c120646f1f90..280fcfb041e47 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -225,11 +225,11 @@ impl<'tcx> InferCtxt<'tcx> { } (ty::ConstKind::Infer(InferConst::Var(vid)), _) => { - return self.unify_const_variable(vid, b, relation.param_env()); + return self.unify_const_variable(vid, b); } (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { - return self.unify_const_variable(vid, a, relation.param_env()); + return self.unify_const_variable(vid, a); } (ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => { @@ -310,7 +310,6 @@ impl<'tcx> InferCtxt<'tcx> { &self, target_vid: ty::ConstVid, ct: ty::Const<'tcx>, - param_env: ty::ParamEnv<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) { ConstVariableValue::Known { value } => { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 0fed4ccc62a83..e1e5d68148fe8 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -1038,7 +1038,6 @@ impl<'tcx> PatRangeBoundary<'tcx> { a.partial_cmp(&b) } ty::Int(ity) => { - use rustc_middle::ty::layout::IntegerExt; let size = rustc_target::abi::Integer::from_int_ty(&tcx, *ity).size(); let a = size.sign_extend(a) as i128; let b = size.sign_extend(b) as i128; diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index a2794a100f14d..417f1932c6f90 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -55,7 +55,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> { fn regions( &mut self, a: ty::Region<'tcx>, - b: ty::Region<'tcx>, + _b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { Ok(a) } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index aa22b8c7c58e0..8a7bfaec870e3 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -541,12 +541,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } #[instrument(level = "trace", skip(self), ret)] - fn eval_rvalue( - &mut self, - rvalue: &Rvalue<'tcx>, - location: Location, - dest: &Place<'tcx>, - ) -> Option<()> { + fn eval_rvalue(&mut self, rvalue: &Rvalue<'tcx>, dest: &Place<'tcx>) -> Option<()> { if !dest.projection.is_empty() { return None; } @@ -733,7 +728,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { _ if place.is_indirect() => {} ConstPropMode::NoPropagation => self.ensure_not_propagated(place.local), ConstPropMode::OnlyInsideOwnBlock | ConstPropMode::FullConstProp => { - if self.eval_rvalue(rvalue, location, place).is_none() { + if self.eval_rvalue(rvalue, place).is_none() { // Const prop failed, so erase the destination, ensuring that whatever happens // from here on, does not know about the previous value. // This is important in case we have diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 3f1497540d25e..30e775733de75 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -10,7 +10,7 @@ use crate::MatchArm; /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned /// in a given column. #[instrument(level = "debug", skip(cx), ret)] -fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( +fn collect_nonexhaustive_missing_variants<'p, 'tcx>( cx: &RustcMatchCheckCtxt<'p, 'tcx>, column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, ) -> Result>, ErrorGuaranteed> { diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 2faa4876798e0..b6ac54a9ab59b 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -52,7 +52,7 @@ impl From for QueryInvocationId { } } -pub(crate) struct MarkFrame<'a> { +pub struct MarkFrame<'a> { index: SerializedDepNodeIndex, parent: Option<&'a MarkFrame<'a>>, } @@ -754,7 +754,6 @@ impl DepGraphData { &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option<()> { let dep_dep_node_color = self.colors.get(parent_dep_node_index); @@ -861,7 +860,7 @@ impl DepGraphData { let prev_deps = self.previous.edge_targets_from(prev_dep_node_index); for dep_dep_node_index in prev_deps { - self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node, Some(&frame))?; + self.try_mark_parent_green(qcx, dep_dep_node_index, Some(&frame))?; } // If we got here without hitting a `return` that means that all diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9788fcb3c7d36..61d43e0493cd7 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1644,7 +1644,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { debug!(?rib.kind); match rib.kind { LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { - let res = self.create_fresh_lifetime(lifetime.id, lifetime.ident, binder); + let res = self.create_fresh_lifetime(lifetime.ident, binder); self.record_lifetime_res(lifetime.id, res, elision_candidate); return; } @@ -1736,7 +1736,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, binder: NodeId) -> LifetimeRes { + fn create_fresh_lifetime(&mut self, ident: Ident, binder: NodeId) -> LifetimeRes { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); debug!(?ident.span); @@ -1757,7 +1757,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_elided_lifetimes_in_path( &mut self, - path_id: NodeId, partial_res: PartialRes, path: &[Segment], source: PathSource<'_>, @@ -1890,7 +1889,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Group all suggestions into the first record. let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for id in node_ids { - let res = self.create_fresh_lifetime(id, ident, binder); + let res = self.create_fresh_lifetime(ident, binder); self.record_lifetime_res( id, res, @@ -3935,7 +3934,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if record_partial_res == RecordPartialRes::Yes { // Avoid recording definition of `A::B` in `::B::C`. self.r.record_partial_res(node_id, partial_res); - self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span); + self.resolve_elided_lifetimes_in_path(partial_res, path, source, path_span); } partial_res diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 915d722dd0206..7026ca6bed75e 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -803,7 +803,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_candidates( &mut self, - mut candidates: Vec>, + candidates: Vec>, ) -> QueryResult<'tcx> { // First try merging all candidates. This is complete and fully sound. let responses = candidates.iter().map(|c| c.result).collect::>(); diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 6984f0ba69473..a7330136fe789 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -124,25 +124,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } - #[instrument(level = "debug", skip(self))] - fn compute_closure_kind_goal( - &mut self, - goal: Goal<'tcx, (DefId, ty::GenericArgsRef<'tcx>, ty::ClosureKind)>, - ) -> QueryResult<'tcx> { - let (_, args, expected_kind) = goal.predicate; - let found_kind = args.as_closure().kind_ty().to_opt_closure_kind(); - - let Some(found_kind) = found_kind else { - return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); - }; - if found_kind.extends(expected_kind) { - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } else { - Err(NoSolution) - } - } - - #[instrument(level = "debug", skip(self))] fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> { if self.tcx().check_is_object_safe(trait_def_id) { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6a6adcbb680ea..4f5e146d2347e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -483,7 +483,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Instead, we select the right impl now but report "`Bar` does // not implement `Clone`". if candidates.len() == 1 { - return self.filter_reservation_impls(candidates.pop().unwrap(), stack.obligation); + return self.filter_reservation_impls(candidates.pop().unwrap()); } // Winnow, but record the exact outcome of evaluation, which @@ -557,7 +557,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // Just one candidate left. - self.filter_reservation_impls(candidates.pop().unwrap().candidate, stack.obligation) + self.filter_reservation_impls(candidates.pop().unwrap().candidate) } /////////////////////////////////////////////////////////////////////////// @@ -1436,7 +1436,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn filter_reservation_impls( &mut self, candidate: SelectionCandidate<'tcx>, - obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { let tcx = self.tcx(); // Treat reservation impls as ambiguity. 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 526/676] 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 527/676] 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 f5d6eb30a845109ab6f69855b4720a15573e8fad Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 30 Jan 2024 22:03:16 +0300 Subject: [PATCH 528/676] hir: Stop keeping prefixes for most of `use` list stems And make sure all other imports have non-empty resolution lists. --- compiler/rustc_ast_lowering/src/item.rs | 19 +++++++++++++------ compiler/rustc_ast_lowering/src/lib.rs | 12 +++++++++--- compiler/rustc_ast_lowering/src/path.rs | 1 + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dd3f7289a60b2..60685119fb98e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -496,8 +496,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - let res = - self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect(); + let res = self.lower_import_res(id, path.span); let path = self.lower_use_path(res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Single) } @@ -533,7 +532,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // for that we return the `{}` import (called the // `ListStem`). - let prefix = Path { segments, span: prefix.span.to(path.span), tokens: None }; + let span = prefix.span.to(path.span); + let prefix = Path { segments, span, tokens: None }; // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { @@ -567,9 +567,16 @@ impl<'hir> LoweringContext<'_, 'hir> { }); } - let res = - self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect(); - let path = self.lower_use_path(res, &prefix, ParamMode::Explicit); + let path = if trees.is_empty() && !prefix.segments.is_empty() { + // For empty lists we need to lower the prefix so it is checked for things + // like stability later. + let res = self.lower_import_res(id, span); + self.lower_use_path(res, &prefix, ParamMode::Explicit) + } else { + // For non-empty lists we can just drop all the data, the prefix is already + // present in HIR as a part of nested imports. + self.arena.alloc(hir::UsePath { res: smallvec![], segments: &[], span }) + }; hir::ItemKind::Use(path, hir::UseKind::ListStem) } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3621844efc8d2..14a83c7eda6db 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -63,7 +63,7 @@ use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{DesugaringKind, Span, DUMMY_SP}; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use thin_vec::ThinVec; @@ -749,8 +749,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) } - fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator> { - self.resolver.get_import_res(id).present_items() + fn lower_import_res(&mut self, id: NodeId, span: Span) -> SmallVec<[Res; 3]> { + let res = self.resolver.get_import_res(id).present_items(); + let res: SmallVec<_> = res.map(|res| self.lower_res(res)).collect(); + if res.is_empty() { + self.dcx().span_delayed_bug(span, "no resolution for an import"); + return smallvec![Res::Err]; + } + res } fn make_lang_item_qpath(&mut self, lang_item: hir::LangItem, span: Span) -> hir::QPath<'hir> { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index c679ee56fcd8b..4df68f8e9297d 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -156,6 +156,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &Path, param_mode: ParamMode, ) -> &'hir hir::UsePath<'hir> { + assert!((1..=3).contains(&res.len())); self.arena.alloc(hir::UsePath { res, segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { From 4c694db25270243597657ec73ec9912f2ddfb0cc Mon Sep 17 00:00:00 2001 From: Conrad Ludgate Date: Sat, 3 Feb 2024 11:44:13 +0000 Subject: [PATCH 529/676] 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 17f0919e8acba48224558c7ebcfc06f14d30d235 Mon Sep 17 00:00:00 2001 From: klensy Date: Sat, 3 Feb 2024 12:33:00 +0300 Subject: [PATCH 530/676] rustc_monomorphize: fix outdated comment in partition --- compiler/rustc_monomorphize/src/partitioning.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 7ff182381b835..032686101d968 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -156,7 +156,7 @@ where placed }; - // Merge until we have at most `max_cgu_count` codegen units. + // Merge until we don't exceed the max CGU count. // `merge_codegen_units` is responsible for updating the CGU size // estimates. { From c5eca333fc8ad2b3f7d45d3a0af59d1cf83df23c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 3 Feb 2024 15:50:14 +0300 Subject: [PATCH 531/676] 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 532/676] 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 533/676] 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 534/676] 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 535/676] 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 536/676] 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 934618fe472727cf5e45535c945516c2c62dd75e Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 3 Feb 2024 19:57:47 -0500 Subject: [PATCH 537/676] Emit a diagnostic for invalid target options --- compiler/rustc_codegen_llvm/messages.ftl | 2 ++ compiler/rustc_codegen_llvm/src/errors.rs | 6 ++++++ compiler/rustc_codegen_llvm/src/llvm_util.rs | 16 ++++++++-------- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index d5bc04f594da1..d14fe0299e64c 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -28,6 +28,8 @@ codegen_llvm_invalid_minimum_alignment_not_power_of_two = codegen_llvm_invalid_minimum_alignment_too_large = invalid minimum global alignment: {$align} is too large +codegen_llvm_invalid_target_feature_prefix = target feature `{$feature}` must begin with a `+` or `-`" + codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}" codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err} diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index d82ff6656f4d3..43250d73b48fe 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -253,3 +253,9 @@ pub struct MismatchedDataLayout<'a> { pub llvm_target: &'a str, pub llvm_layout: &'a str, } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_invalid_target_feature_prefix)] +pub(crate) struct InvalidTargetFeaturePrefix<'a> { + pub feature: &'a str, +} diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 99f4488ac0f97..4bb400b187989 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,7 +1,7 @@ use crate::back::write::create_informational_target_machine; use crate::errors::{ - PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, - UnknownCTargetFeaturePrefix, UnstableCTargetFeature, + InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, + UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; use libc::c_int; @@ -511,7 +511,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Vec Vec Option<&str> { +fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { // features must start with a `+` or `-`. - let feature = s.strip_prefix(&['+', '-'][..]).unwrap_or_else(|| { - bug!("target feature `{}` must begin with a `+` or `-`", s); - }); + let feature = s + .strip_prefix(&['+', '-'][..]) + .unwrap_or_else(|| sess.dcx().emit_fatal(InvalidTargetFeaturePrefix { feature: s })); // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { From a4cb55f2aca24f3cbf33b025c147d7a894bceefd Mon Sep 17 00:00:00 2001 From: trevyn <230691+trevyn@users.noreply.github.com> Date: Sat, 3 Feb 2024 10:37:28 -0800 Subject: [PATCH 538/676] For E0223, suggest methods that look similar to the path --- .../rustc_hir_analysis/src/astconv/mod.rs | 52 ++++++++++++++ tests/ui/suggestions/issue-109195.rs | 20 ++++++ tests/ui/suggestions/issue-109195.stderr | 69 +++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 tests/ui/suggestions/issue-109195.rs create mode 100644 tests/ui/suggestions/issue-109195.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 89f39897ea874..d69f366a66c95 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -29,6 +29,7 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; +use rustc_middle::query::Key; use rustc_middle::ty::{ self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty, TyCtxt, TypeVisitableExt, @@ -1373,6 +1374,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) .emit() // Already reported in an earlier stage. } else { + // suggest methods that look similar to the path + // e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195) + for (_, node) in tcx.hir().parent_iter(qself.hir_id) { + if let hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::Path(hir::QPath::TypeRelative( + hir::Ty { + kind: + hir::TyKind::Path(hir::QPath::TypeRelative( + _, + hir::PathSegment { ident: ident2, .. }, + )), + .. + }, + hir::PathSegment { ident: ident3, .. }, + )), + .. + }) = node + { + let name = format!("{ident2}_{ident3}"); + if if let Some(ty_def_id) = qself_ty.ty_def_id() + && let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id) + && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx + .associated_items(inherent_impl) + .filter_by_name_unhygienic(Symbol::intern(&name)) + .next() + { + true + } else { + qself_ty.is_str() + && ["from_utf8", "from_utf8_mut"].contains(&name.as_str()) + } { + let reported = struct_span_code_err!( + tcx.dcx(), + span, + E0223, + "ambiguous associated type" + ) + .with_span_suggestion_verbose( + ident2.span.to(ident3.span), + format!("you might have meant to use `{name}`"), + name, + Applicability::MaybeIncorrect, + ) + .emit(); + self.set_tainted_by_errors(reported); + return Err(reported); + } + } + } + let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident); diff --git a/tests/ui/suggestions/issue-109195.rs b/tests/ui/suggestions/issue-109195.rs new file mode 100644 index 0000000000000..badb859dbb701 --- /dev/null +++ b/tests/ui/suggestions/issue-109195.rs @@ -0,0 +1,20 @@ +fn main() { + String::from::utf8; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP you might have meant to use `from_utf8` + String::from::utf8(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP you might have meant to use `from_utf8` + String::from::utf16(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP you might have meant to use `from_utf16` + String::from::method_that_doesnt_exist(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `from` + str::from::utf8(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP you might have meant to use `from_utf8` + str::from::utf8_mut(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP you might have meant to use `from_utf8_mut` +} diff --git a/tests/ui/suggestions/issue-109195.stderr b/tests/ui/suggestions/issue-109195.stderr new file mode 100644 index 0000000000000..5c9ef9f98f513 --- /dev/null +++ b/tests/ui/suggestions/issue-109195.stderr @@ -0,0 +1,69 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:2:5 + | +LL | String::from::utf8; + | ^^^^^^^^^^^^ + | +help: you might have meant to use `from_utf8` + | +LL | String::from_utf8; + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:5:5 + | +LL | String::from::utf8(); + | ^^^^^^^^^^^^ + | +help: you might have meant to use `from_utf8` + | +LL | String::from_utf8(); + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:8:5 + | +LL | String::from::utf16(); + | ^^^^^^^^^^^^ + | +help: you might have meant to use `from_utf16` + | +LL | String::from_utf16(); + | ~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:11:5 + | +LL | String::from::method_that_doesnt_exist(); + | ^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path + | +LL | ::from::method_that_doesnt_exist(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:14:5 + | +LL | str::from::utf8(); + | ^^^^^^^^^ + | +help: you might have meant to use `from_utf8` + | +LL | str::from_utf8(); + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:17:5 + | +LL | str::from::utf8_mut(); + | ^^^^^^^^^ + | +help: you might have meant to use `from_utf8_mut` + | +LL | str::from_utf8_mut(); + | ~~~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0223`. From c9192be5611576ecb3200636711356061f804995 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 26 Jan 2024 23:21:21 +0800 Subject: [PATCH 539/676] Reconstify `Add` --- library/core/src/ops/arith.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index bb3cdde66d173..fd50f80474833 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -73,6 +73,7 @@ append_const_msg )] #[doc(alias = "+")] +#[const_trait] pub trait Add { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -94,7 +95,8 @@ pub trait Add { macro_rules! add_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Add for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Add for $t { type Output = $t; #[inline] From 96108c59812bd2a227d6098e0682b2f2811c36c0 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Jan 2024 00:20:52 +0800 Subject: [PATCH 540/676] make effect infer variables suggestable in diagnostics it works when a non-const context that does not enable effects calls into a const effects-enabled trait. We'd simply suggest the non-const trait bound in this case consistent to its fallback. --- compiler/rustc_middle/src/ty/diagnostics.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 8678f388298c2..13cc5cbed443f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -98,6 +98,7 @@ impl<'tcx, T> IsSuggestable<'tcx> for T where T: TypeVisitable> + TypeFoldable>, { + #[tracing::instrument(level = "debug", skip(tcx))] fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool { self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue() } @@ -533,6 +534,9 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { match c.kind() { ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {} + // effect variables are always suggestable, because they are not visible + ConstKind::Infer(InferConst::EffectVar(_)) => {} + ConstKind::Infer(..) | ConstKind::Bound(..) | ConstKind::Placeholder(..) From 74dbf3a070adac13f28f39e2d447b0148998cc40 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 28 Jan 2024 00:22:47 +0800 Subject: [PATCH 541/676] fix ui tests these ui changes are closer to what was there before const_trait_impl changes. --- tests/ui/suggestions/invalid-bin-op.stderr | 4 +++ tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr | 26 +++++++++---------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/tests/ui/suggestions/invalid-bin-op.stderr b/tests/ui/suggestions/invalid-bin-op.stderr index 2bd745c645a1c..018250c8c1b60 100644 --- a/tests/ui/suggestions/invalid-bin-op.stderr +++ b/tests/ui/suggestions/invalid-bin-op.stderr @@ -16,6 +16,10 @@ help: consider annotating `S` with `#[derive(PartialEq)]` LL + #[derive(PartialEq)] LL | struct S(T); | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub fn foo(s: S, t: S) where S: PartialEq { + | +++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index e90784a54ae0d..c1281ce6a422f 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -11,6 +11,19 @@ LL | >::add(1, 2); <&'a i32 as Add> <&i32 as Add<&i32>> +error[E0277]: cannot add `u32` to `i32` + --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 + | +LL | >::add(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` + | + = help: the trait `Add` is not implemented for `i32` + = help: the following other types implement trait `Add`: + + > + <&'a i32 as Add> + <&i32 as Add<&i32>> + error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 | @@ -55,19 +68,6 @@ help: change the type of the numeric literal from `u32` to `i32` LL | >::add(1, 2i32); | ~~~ -error[E0277]: cannot add `u32` to `i32` - --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 - | -LL | >::add(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` - | - = help: the trait `Add` is not implemented for `i32` - = help: the following other types implement trait `Add`: - - > - <&'a i32 as Add> - <&i32 as Add<&i32>> - error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. 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 542/676] 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 543/676] 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 bae4f177b8767f6acab5474c6fec2734df759a32 Mon Sep 17 00:00:00 2001 From: Jarl Evanson Date: Sun, 4 Feb 2024 12:04:39 -0600 Subject: [PATCH 544/676] Enable `structs` SROA MIR-opt test --- tests/mir-opt/remove_storage_markers.rs | 2 +- tests/mir-opt/sroa/structs.rs | 125 ++++++++++++++++++++++-- 2 files changed, 120 insertions(+), 7 deletions(-) diff --git a/tests/mir-opt/remove_storage_markers.rs b/tests/mir-opt/remove_storage_markers.rs index 74e399b6c0eed..27661ab325411 100644 --- a/tests/mir-opt/remove_storage_markers.rs +++ b/tests/mir-opt/remove_storage_markers.rs @@ -7,7 +7,7 @@ // EMIT_MIR remove_storage_markers.main.RemoveStorageMarkers.diff fn main() { - // CHECK-LABLE: fn main( + // CHECK-LABEL: fn main( // CHECK-NOT: StorageDead // CHECK-NOT: StorageLive diff --git a/tests/mir-opt/sroa/structs.rs b/tests/mir-opt/sroa/structs.rs index 73563e12c94fc..5ea3795b86e2d 100644 --- a/tests/mir-opt/sroa/structs.rs +++ b/tests/mir-opt/sroa/structs.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ScalarReplacementOfAggregates // compile-flags: -Cpanic=abort // no-prefer-dynamic @@ -13,28 +12,68 @@ impl Drop for Tag { fn drop(&mut self) {} } +/// Check that SROA excludes structs with a `Drop` implementation. pub fn dropping() { + // CHECK-LABEL: fn dropping( + + // CHECK: [[aggregate:_[0-9]+]]: S; + + // CHECK: bb0: { + // CHECK: [[aggregate]] = S S(Tag(0), Tag(1), Tag(2)).1; } +/// Check that SROA excludes enums. pub fn enums(a: usize) -> usize { + // CHECK-LABEL: fn enums( + + // CHECK: [[enum:_[0-9]+]]: std::option::Option; + + // CHECK: bb0: { + // CHECK: [[enum]] = Option::::Some + // CHECK: _5 = (([[enum]] as Some).0: usize) + // CHECK: _0 = _5 if let Some(a) = Some(a) { a } else { 0 } } +/// Check that SROA destructures `U`. pub fn structs(a: f32) -> f32 { + // CHECK-LABEL: fn structs( struct U { _foo: usize, a: f32, } - + // CHECK: [[ret:_0]]: f32; + // CHECK: [[struct:_[0-9]+]]: structs::U; + // CHECK: [[a_tmp:_[0-9]+]]: f32; + // CHECK: [[foo:_[0-9]+]]: usize; + // CHECK: [[a_ret:_[0-9]+]]: f32; + + // CHECK: bb0: { + // CHECK-NOT: [[struct]] + // CHECK: [[a_tmp]] = _1; + // CHECK-NOT: [[struct]] + // CHECK: [[foo]] = const 0_usize; + // CHECK-NOT: [[struct]] + // CHECK: [[a_ret]] = move [[a_tmp]]; + // CHECK-NOT: [[struct]] + // CHECK: _0 = [[a_ret]]; + // CHECK-NOT: [[struct]] U { _foo: 0, a }.a } +/// Check that SROA excludes unions. pub fn unions(a: f32) -> u32 { + // CHECK-LABEL: fn unions( union Repr { f: f32, u: u32, } + // CHECK: [[union:_[0-9]+]]: unions::Repr; + + // CHECK: bb0: { + // CHECK: [[union]] = Repr { + // CHECK: _0 = ([[union]].1: u32) unsafe { Repr { f: a }.u } } @@ -46,11 +85,21 @@ struct Foo { d: Option, } -fn g() -> u32 { - 3 -} - +/// Check that non-escaping uses of a struct are destructured. pub fn flat() { + // CHECK-LABEL: fn flat( + + // CHECK: [[struct:_[0-9]+]]: Foo; + + // CHECK: bb0: { + // CHECK: [[init_unit:_[0-9]+]] = (); + // CHECK: [[init_opt_isize:_[0-9]+]] = Option::::Some + + // CHECK: [[destr_five:_[0-9]+]] = const 5_u8; + // CHECK: [[destr_unit:_[0-9]+]] = move [[init_unit]]; + // CHECK: [[destr_a:_[0-9]+]] = const "a"; + // CHECK: [[destr_opt_isize:_[0-9]+]] = move [[init_opt_isize]]; + let Foo { a, b, c, d } = Foo { a: 5, b: (), c: "a", d: Some(-4) }; let _ = a; let _ = b; @@ -65,6 +114,10 @@ struct Escaping { c: u32, } +fn g() -> u32 { + 3 +} + fn f(a: *const u32) { println!("{}", unsafe { *a.add(2) }); } @@ -76,10 +129,38 @@ fn f(a: *const u32) { // of them to `f`. However, this would lead to a miscompilation because `b` and `c` // might no longer appear right after `a` in memory. pub fn escaping() { + // CHECK-LABEL: fn escaping( + + // CHECK: [[ptr:_[0-9]+]]: *const u32; + // CHECK: [[ref:_[0-9]+]]: &u32; + // CHECK: [[struct:_[0-9]+]]: Escaping; + // CHECK: [[a:_[0-9]+]]: u32; + + // CHECK: bb0: { + // CHECK: [[struct]] = Escaping { + // CHECK: [[ref]] = &([[struct]].0 + // CHECK: [[ptr]] = &raw const (*[[ref]]); f(&Escaping { a: 1, b: 2, c: g() }.a); } +/// Check that copies from an internal struct are destructured and reassigned to +/// the original struct. fn copies(x: Foo) { + // CHECK-LABEL: fn copies( + + // CHECK: [[external:_[0-9]+]]: Foo) -> + // CHECK: [[internal:_[0-9]+]]: Foo; + // CHECK: [[byte:_[0-9]+]]: u8; + // CHECK: [[unit:_[0-9]+]]: (); + // CHECK: [[str:_[0-9]+]]: &str; + // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option; + + // CHECK: bb0: { + // CHECK: [[byte]] = ([[external]].0 + // CHECK: [[unit]] = ([[external]].1 + // CHECK: [[str]] = ([[external]].2 + // CHECK: [[opt_isize]] = ([[external]].3 + let y = x; let t = y.a; let u = y.c; @@ -87,13 +168,44 @@ fn copies(x: Foo) { let a = z.b; } +/// Check that copies from an internal struct are destructured and reassigned to +/// the original struct. fn ref_copies(x: &Foo) { + // CHECK-LABEL: fn ref_copies( + + // CHECK: [[external:_[0-9]+]]: &Foo) -> + // CHECK: [[internal:_[0-9]+]]: Foo; + // CHECK: [[byte:_[0-9]+]]: u8; + // CHECK: [[unit:_[0-9]+]]: (); + // CHECK: [[str:_[0-9]+]]: &str; + // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option; + + // CHECK: bb0: { + // CHECK: [[byte]] = ((*[[external]]).0 + // CHECK: [[unit]] = ((*[[external]]).1 + // CHECK: [[str]] = ((*[[external]]).2 + // CHECK: [[opt_isize]] = ((*[[external]]).3 + let y = *x; let t = y.a; let u = y.c; } +/// Check that deaggregated assignments from constants are placed after the constant's +/// assignment. Also check that copying field accesses from the copy of the constant are +/// reassigned to copy from the constant. fn constant() { + // CHECK-LABEL: constant( + + // CHECK: [[constant:_[0-9]+]]: (usize, u8); + // CHECK: [[t:_[0-9]+]]: usize; + // CHECK: [[u:_[0-9]+]]: u8; + + // CHECK: bb0: { + // CHECK-NOT: [[constant]] + // CHECK: [[constant]] = const + // CHECK: [[t]] = move ([[constant]].0: usize) + // CHECK: [[u]] = move ([[constant]].1: u8) const U: (usize, u8) = (5, 9); let y = U; let t = y.0; @@ -101,6 +213,7 @@ fn constant() { } fn main() { + // CHECK-LABEL: fn main( dropping(); enums(5); structs(5.); From f47cb984b6266555a17c91f727f44a76f60fa17c Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 30 Jan 2024 14:19:07 -0500 Subject: [PATCH 545/676] Re-enable M1 runners on GitHub Actions This reverts commit 0f9844d10cc8210f1c0ef784ef8d67a1e073c3c1. --- .github/workflows/ci.yml | 20 ++++++++++++++++---- src/ci/github-actions/ci.yml | 36 ++++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02a2193ad883f..1f7776be6c4ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -364,8 +364,8 @@ jobs: os: macos-13 - 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" + SCRIPT: "./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin" + RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 SELECT_XCODE: /Applications/Xcode_13.4.1.app USE_XCODE_CLANG: 1 @@ -375,8 +375,20 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - JEMALLOC_SYS_WITH_LG_PAGE: 14 - os: macos-13 + os: macos-13-xlarge + - name: aarch64-apple + env: + SCRIPT: "./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin" + RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_13.4.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + os: macos-13-xlarge - name: x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 61e0e2c0bc7f5..7ebf65a3184a3 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -555,16 +555,14 @@ jobs: # This target only needs to support 11.0 and up as nothing else supports the hardware - name: dist-aarch64-apple env: - SCRIPT: ./x.py dist bootstrap --include-default-paths --stage 2 + SCRIPT: ./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin 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 + --set rust.lto=thin RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 SELECT_XCODE: /Applications/Xcode_13.4.1.app USE_XCODE_CLANG: 1 @@ -574,15 +572,25 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - # Corresponds to 16K page size - # - # Shouldn't be needed if jemalloc-sys is updated to - # handle this platform like iOS or if we build on - # aarch64-apple-darwin itself. - # - # https://github.com/gnzlbg/jemallocator/blob/c27a859e98e3cb790dc269773d9da71a1e918458/jemalloc-sys/build.rs#L237 - JEMALLOC_SYS_WITH_LG_PAGE: 14 - <<: *job-macos-xl + <<: *job-macos-m1 + + # This target only needs to support 11.0 and up as nothing else supports the hardware + - name: aarch64-apple + env: + SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin + RUST_CONFIGURE_ARGS: >- + --enable-sanitizers + --enable-profiler + --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_13.4.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + <<: *job-macos-m1 ###################### # Windows Builders # From c2573c7574027bf9c939fd7eda6ea3815df23e62 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 30 Jan 2024 14:24:32 -0500 Subject: [PATCH 546/676] Use new publicly-available M1 runners https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/ --- .github/workflows/ci.yml | 4 ++-- src/ci/github-actions/ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f7776be6c4ce..26e589c092eda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -375,7 +375,7 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - os: macos-13-xlarge + os: macos-14 - name: aarch64-apple env: SCRIPT: "./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin" @@ -388,7 +388,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-13-xlarge + os: macos-14 - name: x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 7ebf65a3184a3..43e48c01176f3 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -93,7 +93,7 @@ x--expand-yaml-anchors--remove: <<: *base-job - &job-macos-m1 - os: macos-13-xlarge + os: macos-14 <<: *base-job - &job-windows-8c From 285d8c225d05966040f6a69bfdea83165b54483f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 3 Feb 2024 01:32:01 +0100 Subject: [PATCH 547/676] Suggest `[tail @ ..]` on `[..tail]` and `[...tail]` where `tail` is unresolved --- compiler/rustc_resolve/messages.ftl | 3 + compiler/rustc_resolve/src/errors.rs | 14 +++++ .../rustc_resolve/src/late/diagnostics.rs | 38 +++++++----- ...-pattern-meant-to-be-slice-rest-pattern.rs | 16 ++++- ...tern-meant-to-be-slice-rest-pattern.stderr | 61 +++++++++++++++++-- 5 files changed, 112 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 02847a0f5f914..769c469a5ab2b 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -292,6 +292,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here = resolve_unexpected_res_change_ty_to_const_param_sugg = you might have meant to write a const parameter here +resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg = + if you meant to collect the rest of the slice in `{$ident}`, use the at operator + resolve_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 655fc9812d747..49a0e597dbc75 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -800,3 +800,17 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg { #[applicability] pub applicability: Applicability, } + +#[derive(Subdiagnostic)] +#[suggestion( + resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg, + code = "{snippet}", + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg { + #[primary_span] + pub span: Span, + pub ident: Ident, + pub snippet: String, +} diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 310c126213ad2..5d712461993d8 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1077,24 +1077,34 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, path: &[Segment], ) { - if let Some(pat) = self.diagnostic_metadata.current_pat - && let ast::PatKind::Range(Some(start), None, range) = &pat.kind - && let ExprKind::Path(None, range_path) = &start.kind + let Some(pat) = self.diagnostic_metadata.current_pat else { return }; + let (bound, side, range) = match &pat.kind { + ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range), + ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range), + _ => return, + }; + if let ExprKind::Path(None, range_path) = &bound.kind && let [segment] = &range_path.segments[..] && let [s] = path && segment.ident == s.ident + && segment.ident.span.eq_ctxt(range.span) { - // We've encountered `[first, rest..]` where the user might have meant - // `[first, rest @ ..]` (#88404). - err.span_suggestion_verbose( - segment.ident.span.between(range.span), - format!( - "if you meant to collect the rest of the slice in `{}`, use the at operator", - segment.ident, - ), - " @ ", - Applicability::MaybeIncorrect, - ); + // We've encountered `[first, rest..]` (#88404) or `[first, ..rest]` (#120591) + // where the user might have meant `[first, rest @ ..]`. + let (span, snippet) = match side { + Side::Start => (segment.ident.span.between(range.span), " @ ".into()), + Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)), + }; + err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg { + span, + ident: segment.ident, + snippet, + }); + } + + enum Side { + Start, + End, } } diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs index a619fcafc8614..1eba7aeb4d64a 100644 --- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs +++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs @@ -1,9 +1,23 @@ fn main() { match &[1, 2, 3][..] { - [1, rest..] => println!("{rest:?}"), + [1, rest..] => println!("{rest}"), //~^ ERROR cannot find value `rest` in this scope //~| ERROR cannot find value `rest` in this scope //~| ERROR `X..` patterns in slices are experimental _ => {} } + match &[4, 5, 6][..] { + [] => {} + [_, ..tail] => println!("{tail}"), + //~^ ERROR cannot find value `tail` in this scope + //~| ERROR cannot find value `tail` in this scope + //~| ERROR exclusive range pattern syntax is experimental + } + match &[7, 8, 9][..] { + [] => {} + [_, ...tail] => println!("{tail}"), + //~^ ERROR cannot find value `tail` in this scope + //~| ERROR cannot find value `tail` in this scope + //~| ERROR range-to patterns with `...` are not allowed + } } diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr index c3c9131b63eb2..3a19517c85bd2 100644 --- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr +++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr @@ -1,31 +1,82 @@ +error: range-to patterns with `...` are not allowed + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:13 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^ help: use `..=` instead + error[E0425]: cannot find value `rest` in this scope --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), | ^^^^ not found in this scope | help: if you meant to collect the rest of the slice in `rest`, use the at operator | -LL | [1, rest @ ..] => println!("{rest:?}"), +LL | [1, rest @ ..] => println!("{rest}"), | + error[E0425]: cannot find value `rest` in this scope --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:35 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), + | ^^^^ not found in this scope + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:15 + | +LL | [_, ..tail] => println!("{tail}"), + | ^^^^ not found in this scope + | +help: if you meant to collect the rest of the slice in `tail`, use the at operator + | +LL | [_, tail @ ..] => println!("{tail}"), + | ~~~~~~~~~ + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:35 + | +LL | [_, ..tail] => println!("{tail}"), | ^^^^ not found in this scope +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:16 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^^ not found in this scope + | +help: if you meant to collect the rest of the slice in `tail`, use the at operator + | +LL | [_, tail @ ..] => println!("{tail}"), + | ~~~~~~~~~ + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:36 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^^ not found in this scope + error[E0658]: `X..` patterns in slices are experimental --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), | ^^^^^^ | = note: see issue #67264 for more information = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:13 + | +LL | [_, ..tail] => println!("{tail}"), + | ^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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: use an inclusive range pattern, like N..=M + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0425, E0658. For more information about an error, try `rustc --explain E0425`. From e8c3cbf44b9f003482871e8638859c8f65b234bb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jan 2024 09:25:42 +1100 Subject: [PATCH 548/676] Make `Diagnostic::is_error` return false for `Level::FailureNote`. It doesn't affect behaviour, but makes sense with (a) `FailureNote` having `()` as its emission guarantee, and (b) in `Level` the `is_error` levels now are all listed before the non-`is_error` levels. --- compiler/rustc_errors/src/diagnostic.rs | 4 ++-- compiler/rustc_errors/src/lib.rs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 8ad4925cff288..09570fe74b6ff 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -238,8 +238,7 @@ impl Diagnostic { Level::Bug | Level::DelayedBug(DelayedBugKind::Normal) | Level::Fatal - | Level::Error - | Level::FailureNote => true, + | Level::Error => true, Level::ForceWarning(_) | Level::Warning @@ -248,6 +247,7 @@ impl Diagnostic { | Level::OnceNote | Level::Help | Level::OnceHelp + | Level::FailureNote | Level::Allow | Level::Expect(_) => false, } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b2bd4d8eb956e..42b1c85e93968 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1541,6 +1541,8 @@ pub enum Level { /// /// The [`LintExpectationId`] is used for expected lint diagnostics. In all other cases this /// should be `None`. + /// + /// Its `EmissionGuarantee` is `()`. ForceWarning(Option), /// A warning about the code being compiled. Does not prevent compilation from finishing. @@ -1570,7 +1572,8 @@ pub enum Level { /// Its `EmissionGuarantee` is `()`. OnceHelp, - /// Similar to `Note`, but used in cases where compilation has failed. Rare. + /// Similar to `Note`, but used in cases where compilation has failed. When printed for human + /// consumption, it doesn't have any kind of `note:` label. Rare. /// /// Its `EmissionGuarantee` is `()`. FailureNote, From 5dd0431386867a051f726cbba6e0f46f7bba5e5d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jan 2024 13:56:22 +1100 Subject: [PATCH 549/676] Tighten the assertion in `downgrade_to_delayed_bug`. I.e. `Bug` and `Fatal` level diagnostics are never downgraded. --- compiler/rustc_errors/src/diagnostic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 09570fe74b6ff..299e4a840f726 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -306,7 +306,7 @@ impl Diagnostic { #[track_caller] pub fn downgrade_to_delayed_bug(&mut self) { assert!( - self.is_error(), + matches!(self.level, Level::Error | Level::DelayedBug(_)), "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error", self.level ); From 0211221e9001314d54ece16e2634d51948f3ecb3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 2 Feb 2024 16:09:34 +0100 Subject: [PATCH 550/676] Prevent running some code if it is already in the map --- src/librustdoc/clean/inline.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index aab974ad79edd..f65c09bf0e810 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -196,6 +196,14 @@ pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [ast: /// These names are used later on by HTML rendering to generate things like /// source links back to the original item. pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) { + if did.is_local() { + if cx.cache.exact_paths.contains_key(&did) { + return; + } + } else if cx.cache.external_paths.contains_key(&did) { + return; + } + let crate_name = cx.tcx.crate_name(did.krate); let relative = From c3673868325f95203d5291f2fa3a399425c14876 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jan 2024 15:10:23 +1100 Subject: [PATCH 551/676] Refactor `emit_diagnostic`. - Combine two different blocks involving `diagnostic.level.get_expectation_id()` into one. - Combine several `if`s involving `diagnostic.level` into a single `match`. This requires reordering some of the operations, but this has no functional effect. --- compiler/rustc_errors/src/lib.rs | 82 +++++++++++++++----------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 42b1c85e93968..b3461b676be27 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1247,24 +1247,41 @@ impl DiagCtxtInner { } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { - // The `LintExpectationId` can be stable or unstable depending on when it was created. - // Diagnostics created before the definition of `HirId`s are unstable and can not yet - // 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); - return None; + if let Some(expectation_id) = diagnostic.level.get_expectation_id() { + // The `LintExpectationId` can be stable or unstable depending on when it was created. + // Diagnostics created before the definition of `HirId`s are unstable and can not yet + // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by + // a stable one by the `LintLevelsBuilder`. + if let LintExpectationId::Unstable { .. } = expectation_id { + self.unstable_expect_diagnostics.push(diagnostic); + return None; + } + self.suppressed_expected_diag = true; + self.fulfilled_expectations.insert(expectation_id.normalize()); + } + + if diagnostic.has_future_breakage() { + // Future breakages aren't emitted if they're Level::Allow, + // but they still need to be constructed and stashed below, + // so they'll trigger the good-path bug check. + self.suppressed_expected_diag = true; + self.future_breakage_diagnostics.push(diagnostic.clone()); + } + + if matches!(diagnostic.level, DelayedBug(_)) && self.flags.eagerly_emit_delayed_bugs { + diagnostic.level = Error; } - // FIXME(eddyb) this should check for `has_errors` and stop pushing - // once *any* errors were emitted (and truncate `span_delayed_bugs` - // when an error is first emitted, also), but maybe there's a case - // in which that's not sound? otherwise this is really inefficient. match diagnostic.level { - DelayedBug(_) if self.flags.eagerly_emit_delayed_bugs => { - diagnostic.level = Error; + // This must come after the possible promotion of `DelayedBug` to `Error` above. + Fatal | Error if self.treat_next_err_as_bug() => { + diagnostic.level = Bug; } DelayedBug(DelayedBugKind::Normal) => { + // FIXME(eddyb) this should check for `has_errors` and stop pushing + // once *any* errors were emitted (and truncate `span_delayed_bugs` + // when an error is first emitted, also), but maybe there's a case + // in which that's not sound? otherwise this is really inefficient. let backtrace = std::backtrace::Backtrace::capture(); self.span_delayed_bugs .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); @@ -1277,38 +1294,17 @@ impl DiagCtxtInner { .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); return None; } - _ => {} - } - - // This must come after the possible promotion of `DelayedBug` to - // `Error` above. - if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() { - diagnostic.level = Bug; - } - - if diagnostic.has_future_breakage() { - // Future breakages aren't emitted if they're Level::Allow, - // but they still need to be constructed and stashed below, - // so they'll trigger the good-path bug check. - self.suppressed_expected_diag = true; - self.future_breakage_diagnostics.push(diagnostic.clone()); - } - - if let Some(expectation_id) = diagnostic.level.get_expectation_id() { - self.suppressed_expected_diag = true; - self.fulfilled_expectations.insert(expectation_id.normalize()); - } - - if diagnostic.level == Warning && !self.flags.can_emit_warnings { - if diagnostic.has_future_breakage() { + Warning if !self.flags.can_emit_warnings => { + if diagnostic.has_future_breakage() { + (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); + } + return None; + } + Allow | Expect(_) => { (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); + return None; } - return None; - } - - if matches!(diagnostic.level, Expect(_) | Allow) { - (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); - return None; + _ => {} } let mut guaranteed = None; From 59e0bc2de7134a2d88e9c14db32884e631e90373 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jan 2024 11:23:54 +1100 Subject: [PATCH 552/676] Split `Level::DelayedBug` in two. The two kinds of delayed bug have quite different semantics so a stronger conceptual separation is nice. (`is_error` is a good example, because the two kinds have different behaviour.) The commit also moves the `DelayedBug` variant after `Error` in `Level`, to reflect the fact that it's weaker than `Error` -- it might trigger an error but also might not. (The pre-existing `downgrade_to_delayed_bug` function also reflects the notion that delayed bugs are lower/after normal errors.) Plus it condenses some of the comments on `Level` into a table, for easier reading, and introduces `can_be_top_or_sub` to indicate which levels can be used in top-level diagnostics vs. subdiagnostics. Finally, it renames `DiagCtxtInner::span_delayed_bugs` as `DiagCtxtInner::delayed_bugs`. The `span_` prefix is unnecessary because some delayed bugs don't have a span. --- compiler/rustc_error_messages/src/lib.rs | 2 +- .../src/annotate_snippet_emitter_writer.rs | 6 +- compiler/rustc_errors/src/diagnostic.rs | 18 +- compiler/rustc_errors/src/emitter.rs | 1 + compiler/rustc_errors/src/lib.rs | 159 ++++++++++-------- .../equality-in-canonical-query.clone.stderr | 2 +- ...equality_in_canonical_query.current.stderr | 2 +- 7 files changed, 101 insertions(+), 89 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 8fd7c5764797e..d212e18b4cd72 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -378,7 +378,7 @@ impl From> for DiagnosticMessage { } } -/// A workaround for "good path" ICEs when formatting types in disabled lints. +/// A workaround for good_path_delayed_bug ICEs when formatting types in disabled lints. /// /// Delays formatting until `.into(): DiagnosticMessage` is used. pub struct DelayDm(pub F); diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 949f52ef6b586..06f6c58c5ff2e 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -85,7 +85,11 @@ fn source_string(file: Lrc, line: &Line) -> String { /// Maps `Diagnostic::Level` to `snippet::AnnotationType` fn annotation_type_for_level(level: Level) -> AnnotationType { match level { - Level::Bug | Level::DelayedBug(_) | Level::Fatal | Level::Error => AnnotationType::Error, + Level::Bug + | Level::Fatal + | Level::Error + | Level::DelayedBug + | Level::GoodPathDelayedBug => AnnotationType::Error, Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning, Level::Note | Level::OnceNote => AnnotationType::Note, Level::Help | Level::OnceHelp => AnnotationType::Help, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 299e4a840f726..1763c355069a9 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,8 +1,7 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, - ErrCode, Level, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, - SuggestionStyle, + CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, ErrCode, Level, + MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_error_messages::fluent_value_from_str_list_sep_by_and; @@ -235,14 +234,11 @@ impl Diagnostic { pub fn is_error(&self) -> bool { match self.level { - Level::Bug - | Level::DelayedBug(DelayedBugKind::Normal) - | Level::Fatal - | Level::Error => true, + Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true, - Level::ForceWarning(_) + Level::GoodPathDelayedBug + | Level::ForceWarning(_) | Level::Warning - | Level::DelayedBug(DelayedBugKind::GoodPath) | Level::Note | Level::OnceNote | Level::Help @@ -306,11 +302,11 @@ impl Diagnostic { #[track_caller] pub fn downgrade_to_delayed_bug(&mut self) { assert!( - matches!(self.level, Level::Error | Level::DelayedBug(_)), + matches!(self.level, Level::Error | Level::DelayedBug), "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error", self.level ); - self.level = Level::DelayedBug(DelayedBugKind::Normal); + self.level = Level::DelayedBug; } /// Appends a labeled span to the diagnostic. diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 4be5ed923e5e0..6370e1d387c37 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2116,6 +2116,7 @@ impl HumanEmitter { } if !self.short_message { for child in children { + assert!(child.level.can_be_top_or_sub().1); let span = &child.span; if let Err(err) = self.emit_messages_default_inner( span, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b3461b676be27..cfb2dfbeb984a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -439,7 +439,7 @@ struct DiagCtxtInner { has_printed: bool, emitter: Box, - span_delayed_bugs: Vec, + delayed_bugs: Vec, good_path_delayed_bugs: Vec, /// This flag indicates that an expected diagnostic was emitted and suppressed. /// This is used for the `good_path_delayed_bugs` check. @@ -523,8 +523,7 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { pub static TRACK_DIAGNOSTIC: AtomicRef = AtomicRef::new(&(default_track_diagnostic as _)); -#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] -pub enum DelayedBugKind { +enum DelayedBugKind { Normal, GoodPath, } @@ -557,11 +556,6 @@ impl Drop for DiagCtxtInner { self.flush_delayed(DelayedBugKind::Normal) } - // FIXME(eddyb) this explains what `good_path_delayed_bugs` are! - // They're `span_delayed_bugs` but for "require some diagnostic happened" - // instead of "require some error happened". Sadly that isn't ideal, as - // lints can be `#[allow]`'d, potentially leading to this triggering. - // Also, "good path" should be replaced with a better naming. if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() { self.flush_delayed(DelayedBugKind::GoodPath); } @@ -608,7 +602,7 @@ impl DiagCtxt { deduplicated_warn_count: 0, has_printed: false, emitter, - span_delayed_bugs: Vec::new(), + delayed_bugs: Vec::new(), good_path_delayed_bugs: Vec::new(), suppressed_expected_diag: false, taught_diagnostics: Default::default(), @@ -664,7 +658,7 @@ impl DiagCtxt { inner.has_printed = false; // actually free the underlying memory (which `clear` would not do) - inner.span_delayed_bugs = Default::default(); + inner.delayed_bugs = Default::default(); inner.good_path_delayed_bugs = Default::default(); inner.taught_diagnostics = Default::default(); inner.emitted_diagnostic_codes = Default::default(); @@ -865,8 +859,7 @@ impl DiagCtxt { /// directly). #[track_caller] pub fn delayed_bug(&self, msg: impl Into) -> ErrorGuaranteed { - DiagnosticBuilder::::new(self, DelayedBug(DelayedBugKind::Normal), msg) - .emit() + DiagnosticBuilder::::new(self, DelayedBug, msg).emit() } /// Like `delayed_bug`, but takes an additional span. @@ -879,15 +872,12 @@ impl DiagCtxt { sp: impl Into, msg: impl Into, ) -> ErrorGuaranteed { - DiagnosticBuilder::::new(self, DelayedBug(DelayedBugKind::Normal), msg) - .with_span(sp) - .emit() + DiagnosticBuilder::::new(self, DelayedBug, msg).with_span(sp).emit() } - // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's - // where the explanation of what "good path" is (also, it should be renamed). + /// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`. pub fn good_path_delayed_bug(&self, msg: impl Into) { - DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit() + DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit() } #[track_caller] @@ -961,7 +951,7 @@ impl DiagCtxt { pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option { let inner = self.inner.borrow(); let result = - inner.has_errors() || inner.lint_err_count > 0 || !inner.span_delayed_bugs.is_empty(); + inner.has_errors() || inner.lint_err_count > 0 || !inner.delayed_bugs.is_empty(); result.then(|| { #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() @@ -1247,6 +1237,8 @@ impl DiagCtxtInner { } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { + assert!(diagnostic.level.can_be_top_or_sub().0); + if let Some(expectation_id) = diagnostic.level.get_expectation_id() { // The `LintExpectationId` can be stable or unstable depending on when it was created. // Diagnostics created before the definition of `HirId`s are unstable and can not yet @@ -1268,27 +1260,29 @@ impl DiagCtxtInner { self.future_breakage_diagnostics.push(diagnostic.clone()); } - if matches!(diagnostic.level, DelayedBug(_)) && self.flags.eagerly_emit_delayed_bugs { + if matches!(diagnostic.level, DelayedBug | GoodPathDelayedBug) + && self.flags.eagerly_emit_delayed_bugs + { diagnostic.level = Error; } match diagnostic.level { - // This must come after the possible promotion of `DelayedBug` to `Error` above. + // This must come after the possible promotion of `DelayedBug`/`GoodPathDelayedBug` to + // `Error` above. Fatal | Error if self.treat_next_err_as_bug() => { diagnostic.level = Bug; } - DelayedBug(DelayedBugKind::Normal) => { + DelayedBug => { // FIXME(eddyb) this should check for `has_errors` and stop pushing - // once *any* errors were emitted (and truncate `span_delayed_bugs` + // once *any* errors were emitted (and truncate `delayed_bugs` // when an error is first emitted, also), but maybe there's a case // in which that's not sound? otherwise this is really inefficient. let backtrace = std::backtrace::Backtrace::capture(); - self.span_delayed_bugs - .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); + self.delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); #[allow(deprecated)] return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); } - DelayedBug(DelayedBugKind::GoodPath) => { + GoodPathDelayedBug => { let backtrace = std::backtrace::Backtrace::capture(); self.good_path_delayed_bugs .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); @@ -1392,12 +1386,12 @@ impl DiagCtxtInner { fn flush_delayed(&mut self, kind: DelayedBugKind) { let (bugs, note1) = match kind { DelayedBugKind::Normal => ( - std::mem::take(&mut self.span_delayed_bugs), - "no errors encountered even though `span_delayed_bug` issued", + std::mem::take(&mut self.delayed_bugs), + "no errors encountered even though delayed bugs were created", ), DelayedBugKind::GoodPath => ( std::mem::take(&mut self.good_path_delayed_bugs), - "no warnings or errors encountered even though `good_path_delayed_bugs` issued", + "no warnings or errors encountered even though good path delayed bugs were created", ), }; let note2 = "those delayed bugs will now be shown as internal compiler errors"; @@ -1436,8 +1430,8 @@ impl DiagCtxtInner { let mut bug = if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; - // "Undelay" the `DelayedBug`s (into plain `Bug`s). - if !matches!(bug.level, DelayedBug(_)) { + // "Undelay" the delayed bugs (into plain `Bug`s). + if !matches!(bug.level, DelayedBug | GoodPathDelayedBug) { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { @@ -1503,85 +1497,89 @@ impl DelayedDiagnostic { } } +/// Level is_error EmissionGuarantee Top-level Sub Used in lints? +/// ----- -------- ----------------- --------- --- -------------- +/// Bug yes BugAbort yes - - +/// Fatal yes FatalAbort/FatalError(*) yes - - +/// Error yes ErrorGuaranteed yes - yes +/// DelayedBug yes ErrorGuaranteed yes - - +/// GoodPathDelayedBug - () yes - - +/// ForceWarning - () yes - lint-only +/// Warning - () yes yes yes +/// Note - () rare yes - +/// OnceNote - () - yes lint-only +/// Help - () rare yes - +/// OnceHelp - () - yes lint-only +/// FailureNote - () rare - - +/// Allow - () yes - lint-only +/// Expect - () yes - lint-only +/// +/// (*) `FatalAbort` normally, `FatalError` in the non-aborting "almost fatal" case that is +/// occasionally used. +/// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { /// For bugs in the compiler. Manifests as an ICE (internal compiler error) panic. - /// - /// Its `EmissionGuarantee` is `BugAbort`. Bug, - /// This is a strange one: lets you register an error without emitting it. If compilation ends - /// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be - /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths - /// that should only be reached when compiling erroneous code. - /// - /// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for - /// `GoodPath` delayed bugs. - DelayedBug(DelayedBugKind), - /// An error that causes an immediate abort. Used for things like configuration errors, /// internal overflows, some file operation errors. - /// - /// Its `EmissionGuarantee` is `FatalAbort`, except in the non-aborting "almost fatal" case - /// that is occasionally used, where it is `FatalError`. Fatal, /// An error in the code being compiled, which prevents compilation from finishing. This is the /// most common case. - /// - /// Its `EmissionGuarantee` is `ErrorGuaranteed`. Error, + /// This is a strange one: lets you register an error without emitting it. If compilation ends + /// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be + /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths + /// that should only be reached when compiling erroneous code. + DelayedBug, + + /// Like `DelayedBug`, but weaker: lets you register an error without emitting it. If + /// compilation ends without any other diagnostics being emitted (and without an expected lint + /// being suppressed), this will be emitted as a bug. Otherwise, it will be silently dropped. + /// I.e. "expect other diagnostics are emitted (or suppressed)" semantics. Useful on code paths + /// that should only be reached when emitting diagnostics, e.g. for expensive one-time + /// diagnostic formatting operations. + /// + /// FIXME(nnethercote) good path delayed bugs are semantically strange: if printed they produce + /// an ICE, but they don't satisfy `is_error` and they don't guarantee an error is emitted. + /// Plus there's the extra complication with expected (suppressed) lints. They have limited + /// use, and are used in very few places, and "good path" isn't a good name. It would be good + /// to remove them. + GoodPathDelayedBug, + /// A `force-warn` lint warning about the code being compiled. Does not prevent compilation /// from finishing. /// /// The [`LintExpectationId`] is used for expected lint diagnostics. In all other cases this /// should be `None`. - /// - /// Its `EmissionGuarantee` is `()`. ForceWarning(Option), /// A warning about the code being compiled. Does not prevent compilation from finishing. - /// - /// Its `EmissionGuarantee` is `()`. Warning, - /// A message giving additional context. Rare, because notes are more commonly attached to other - /// diagnostics such as errors. - /// - /// Its `EmissionGuarantee` is `()`. + /// A message giving additional context. Note, - /// A note that is only emitted once. Rare, mostly used in circumstances relating to lints. - /// - /// Its `EmissionGuarantee` is `()`. + /// A note that is only emitted once. OnceNote, - /// A message suggesting how to fix something. Rare, because help messages are more commonly - /// attached to other diagnostics such as errors. - /// - /// Its `EmissionGuarantee` is `()`. + /// A message suggesting how to fix something. Help, - /// A help that is only emitted once. Rare. - /// - /// Its `EmissionGuarantee` is `()`. + /// A help that is only emitted once. OnceHelp, /// Similar to `Note`, but used in cases where compilation has failed. When printed for human - /// consumption, it doesn't have any kind of `note:` label. Rare. - /// - /// Its `EmissionGuarantee` is `()`. + /// consumption, it doesn't have any kind of `note:` label. FailureNote, /// Only used for lints. - /// - /// Its `EmissionGuarantee` is `()`. Allow, /// Only used for lints. - /// - /// Its `EmissionGuarantee` is `()`. Expect(LintExpectationId), } @@ -1595,7 +1593,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | DelayedBug(_) | Fatal | Error => { + Bug | Fatal | Error | DelayedBug | GoodPathDelayedBug => { spec.set_fg(Some(Color::Red)).set_intense(true); } ForceWarning(_) | Warning => { @@ -1615,7 +1613,7 @@ impl Level { pub fn to_str(self) -> &'static str { match self { - Bug | DelayedBug(_) => "error: internal compiler error", + Bug | DelayedBug | GoodPathDelayedBug => "error: internal compiler error", Fatal | Error => "error", ForceWarning(_) | Warning => "warning", Note | OnceNote => "note", @@ -1635,6 +1633,19 @@ impl Level { _ => None, } } + + // Can this level be used in a top-level diagnostic message and/or a + // subdiagnostic message? + fn can_be_top_or_sub(&self) -> (bool, bool) { + match self { + Bug | DelayedBug | Fatal | Error | GoodPathDelayedBug | ForceWarning(_) + | FailureNote | Allow | Expect(_) => (true, false), + + Warning | Note | Help => (true, true), + + OnceNote | OnceHelp => (false, true), + } + } } // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite. diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr index 1011fc4163bca..0e3cd2ff06099 100644 --- a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr +++ b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr @@ -1,4 +1,4 @@ -note: no errors encountered even though `span_delayed_bug` issued +note: no errors encountered even though delayed bugs were created note: those delayed bugs will now be shown as internal compiler errors diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr index d92bafce142c2..fd76526644bdd 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr @@ -1,4 +1,4 @@ -note: no errors encountered even though `span_delayed_bug` issued +note: no errors encountered even though delayed bugs were created note: those delayed bugs will now be shown as internal compiler errors From fe420dc46ecf988eb13c34526feea18fd8daef6b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 22 Jan 2024 13:56:37 +1100 Subject: [PATCH 553/676] 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 554/676] 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 555/676] 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 556/676] 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 557/676] 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 d6221957e03d017d2763bd6635f88548984176eb Mon Sep 17 00:00:00 2001 From: Chris Copeland Date: Sun, 4 Feb 2024 15:28:35 -0800 Subject: [PATCH 558/676] Add an `armv8r-none-eabihf` target to support the Cortex-R52. --- compiler/rustc_target/src/spec/mod.rs | 1 + .../src/spec/targets/armv8r_none_eabihf.rs | 35 ++++++++++++++++ src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../src/platform-support/arm-none-eabi.md | 1 + .../platform-support/armv8r-none-eabihf.md | 40 +++++++++++++++++++ src/tools/build-manifest/src/main.rs | 1 + tests/assembly/targets/targets-elf.rs | 3 ++ 8 files changed, 83 insertions(+) create mode 100644 compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs create mode 100644 src/doc/rustc/src/platform-support/armv8r-none-eabihf.md diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 6c698c5b01dd5..a57255db795ac 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1543,6 +1543,7 @@ supported_targets! { ("armebv7r-none-eabihf", armebv7r_none_eabihf), ("armv7r-none-eabi", armv7r_none_eabi), ("armv7r-none-eabihf", armv7r_none_eabihf), + ("armv8r-none-eabihf", armv8r_none_eabihf), ("x86_64-pc-solaris", x86_64_pc_solaris), ("sparcv9-sun-solaris", sparcv9_sun_solaris), diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs new file mode 100644 index 0000000000000..28dba4f7f5d83 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs @@ -0,0 +1,35 @@ +// Targets the Little-endian Cortex-R52 processor (ARMv8-R) + +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "armv8r-none-eabihf".into(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + + options: TargetOptions { + abi: "eabihf".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + relocation_model: RelocModel::Static, + panic_strategy: PanicStrategy::Abort, + // The Cortex-R52 has two variants with respect to floating-point support: + // 1. fp-armv8, SP-only, with 16 DP (32 SP) registers + // 2. neon-fp-armv8, SP+DP, with 32 DP registers + // Use the lesser of these two options as the default, as it will produce code + // compatible with either variant. + // + // Reference: + // Arm Cortex-R52 Processor Technical Reference Manual + // - Chapter 15 Advanced SIMD and floating-point support + features: "+fp-armv8,-fp64,-d32".into(), + max_atomic_width: Some(64), + emit_debug_gdb_scripts: false, + // GCC defaults to 8 for arm-none here. + c_enum_min_bits: Some(8), + ..Default::default() + }, + } +} diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 1998b008dc811..1f9307203bc3c 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -26,6 +26,7 @@ - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md) - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md) - [armv7r-none-eabi](platform-support/armv7r-none-eabi.md) + - [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f648a60b6c48d..13a7b483d6f3d 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -278,6 +278,7 @@ target | std | host | notes [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat [`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * | | Bare ARMv7-A, hardfloat +[`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare ARMv8-R, hardfloat [`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARMv7-A Apple WatchOS `armv7s-apple-ios` | ✓ | | ARMv7-A Apple-A6 Apple iOS `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 4f76d0d7bbce7..6335a6405a102 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -13,6 +13,7 @@ - [{arm,thumb}v4t-none-eabi](armv4t-none-eabi.md) - [{arm,thumb}v5te-none-eabi](armv5te-none-eabi.md) - armv7a-none-eabihf +- [armv8r-none-eabihf](armv8r-none-eabihf.md) Bare-metal target for 32-bit ARM CPUs. diff --git a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md new file mode 100644 index 0000000000000..588e5d7c99449 --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md @@ -0,0 +1,40 @@ +# `armv8r-none-eabihf` + +**Tier: 3** + +Bare-metal target for CPUs in the ARMv8-R architecture family, supporting +dual ARM/Thumb mode, with ARM mode as the default. + +Processors in this family include the Arm [Cortex-R52][cortex-r52] +and [Cortex-R52+][cortex-r52-plus]. + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. + +[cortex-r52]: https://www.arm.com/products/silicon-ip-cpu/cortex-r/cortex-r52 +[cortex-r52-plus]: https://www.arm.com/products/silicon-ip-cpu/cortex-r/cortex-r52-plus + +## Target maintainers + +- [Chris Copeland](https://github.com/chrisnc), `chris@chrisnc.net` + +## Requirements + +The Cortex-R52 family always includes a floating-point unit, so there is no +non-`hf` version of this target. The floating-point features assumed by this +target are those of the single-precision-only config of the Cortex-R52, which +has 16 double-precision registers, accessible as 32 single-precision registers. +The other variant of Cortex-R52 includes double-precision, 32 double-precision +registers, and Advanced SIMD (Neon). + +The manual refers to this as the "Full Advanced SIMD config". To compile code +for this variant, use: `-C target-feature=+fp64,+d32,+neon`. See the [Advanced +SIMD and floating-point support][fpu] section of the Cortex-R52 Processor +Technical Reference Manual for more details. + +[fpu]: https://developer.arm.com/documentation/100026/0104/Advanced-SIMD-and-floating-point-support/About-the-Advanced-SIMD-and-floating-point-support + +## Cross-compilation toolchains and C code + +This target supports C code compiled with the `arm-none-eabi` target triple and +`-march=armv8-r` or a suitable `-mcpu` flag. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 1ef8cf7de3cd5..808fb0c07ea51 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -83,6 +83,7 @@ static TARGETS: &[&str] = &[ "armebv7r-none-eabihf", "armv7r-none-eabi", "armv7r-none-eabihf", + "armv8r-none-eabihf", "armv7s-apple-ios", "bpfeb-unknown-none", "bpfel-unknown-none", diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 41f5df0fba001..6105ea430ddd3 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -174,6 +174,9 @@ // revisions: armv7r_none_eabihf // [armv7r_none_eabihf] compile-flags: --target armv7r-none-eabihf // [armv7r_none_eabihf] needs-llvm-components: arm +// revisions: armv8r_none_eabihf +// [armv8r_none_eabihf] compile-flags: --target armv8r-none-eabihf +// [armv8r_none_eabihf] needs-llvm-components: arm // FIXME: disabled since it fails on CI saying the csky component is missing /* revisions: csky_unknown_linux_gnuabiv2 From 8266657338994c5dc26f571a3776c2afa6ca150d Mon Sep 17 00:00:00 2001 From: r0cky Date: Mon, 5 Feb 2024 08:07:55 +0800 Subject: [PATCH 559/676] 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 560/676] 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 7f1d523cd025886a1a820a5abc96281510b6baae Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Feb 2024 23:05:34 +0000 Subject: [PATCH 561/676] Avoid emitting trait bound errors of incoherent traits --- .../error_reporting/type_err_ctxt_ext.rs | 14 ++++++++++++++ .../in-trait/coherence-constrained.rs | 2 -- .../in-trait/coherence-constrained.stderr | 19 +++---------------- 3 files changed, 17 insertions(+), 18 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 a8715b0764f0a..b9ef8446fe13b 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 @@ -2364,6 +2364,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return e; } + if let Err(guar) = self.tcx.ensure().coherent_trait(trait_ref.def_id()) { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + return guar; + } + // This is kind of a hack: it frequently happens that some earlier // error prevents types from being fully inferred, and then we get // a bunch of uninteresting errors saying something like " InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(e) = self.tainted_by_errors() { return e; } + + if let Err(guar) = + self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_ty.def_id)) + { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + return guar; + } let subst = data .projection_ty .args diff --git a/tests/ui/async-await/in-trait/coherence-constrained.rs b/tests/ui/async-await/in-trait/coherence-constrained.rs index 8e62b3e0e90bf..82c8724ca3e61 100644 --- a/tests/ui/async-await/in-trait/coherence-constrained.rs +++ b/tests/ui/async-await/in-trait/coherence-constrained.rs @@ -12,7 +12,6 @@ impl Foo for Bar { type T = (); async fn foo(&self) {} - //~^ ERROR type annotations needed: cannot satisfy `::T == ()` } impl Foo for Bar { @@ -20,7 +19,6 @@ impl Foo for Bar { type T = (); async fn foo(&self) {} - //~^ ERROR type annotations needed: cannot satisfy `::T == ()` } fn main() {} diff --git a/tests/ui/async-await/in-trait/coherence-constrained.stderr b/tests/ui/async-await/in-trait/coherence-constrained.stderr index 570a357ca8fb7..5c48a1fe98fc5 100644 --- a/tests/ui/async-await/in-trait/coherence-constrained.stderr +++ b/tests/ui/async-await/in-trait/coherence-constrained.stderr @@ -1,17 +1,5 @@ -error[E0284]: type annotations needed: cannot satisfy `::T == ()` - --> $DIR/coherence-constrained.rs:14:5 - | -LL | async fn foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^ cannot satisfy `::T == ()` - -error[E0284]: type annotations needed: cannot satisfy `::T == ()` - --> $DIR/coherence-constrained.rs:22:5 - | -LL | async fn foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^ cannot satisfy `::T == ()` - error[E0119]: conflicting implementations of trait `Foo` for type `Bar` - --> $DIR/coherence-constrained.rs:18:1 + --> $DIR/coherence-constrained.rs:17:1 | LL | impl Foo for Bar { | ---------------- first implementation here @@ -19,7 +7,6 @@ LL | impl Foo for Bar { LL | impl Foo for Bar { | ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar` -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0284. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0119`. From 9cd6c68033929d60441ad4286d1270eeafbb8620 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Feb 2024 10:51:18 +0100 Subject: [PATCH 562/676] cleanup effect var handling --- .../src/infer/canonical/canonicalizer.rs | 2 +- .../rustc_infer/src/infer/canonical/mod.rs | 8 +++- compiler/rustc_infer/src/infer/freshen.rs | 9 +--- compiler/rustc_infer/src/infer/mod.rs | 15 ++++--- .../rustc_infer/src/infer/relate/combine.rs | 38 +++-------------- compiler/rustc_infer/src/infer/resolve.rs | 9 ++-- compiler/rustc_middle/src/infer/unify_key.rs | 42 ++++++++++--------- 7 files changed, 52 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index e4b37f05b778f..30ca70326fa87 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -480,7 +480,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } ty::ConstKind::Infer(InferConst::EffectVar(vid)) => { match self.infcx.unwrap().probe_effect_var(vid) { - Some(value) => return self.fold_const(value.as_const(self.tcx)), + Some(value) => return self.fold_const(value), None => { return self.canonicalize_const_var( CanonicalVarInfo { kind: CanonicalVarKind::Effect }, diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 386fdb09ba5d5..1f68a5a9c6179 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -24,6 +24,7 @@ use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind}; use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind}; use rustc_index::IndexVec; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, List, Ty, TyCtxt}; @@ -152,7 +153,12 @@ impl<'tcx> InferCtxt<'tcx> { ) .into(), CanonicalVarKind::Effect => { - let vid = self.inner.borrow_mut().effect_unification_table().new_key(None).vid; + let vid = self + .inner + .borrow_mut() + .effect_unification_table() + .new_key(EffectVarValue::Unknown) + .vid; ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool) .into() } diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index d256994d8d1fd..2d5fa1b5c7001 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -151,13 +151,8 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty()) } ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { - let opt_ct = self - .infcx - .inner - .borrow_mut() - .effect_unification_table() - .probe_value(v) - .map(|effect| effect.as_const(self.infcx.tcx)); + let opt_ct = + self.infcx.inner.borrow_mut().effect_unification_table().probe_value(v).known(); self.freshen_const( opt_ct, ty::InferConst::EffectVar(v), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0a39fe007fd22..13baecf6002c0 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -8,6 +8,7 @@ pub use self::ValuePairs::*; pub use relate::combine::ObligationEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::undo_log::UndoLogs; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use self::opaque_types::OpaqueTypeStorage; @@ -25,8 +26,8 @@ use rustc_data_structures::unify as ut; use rustc_errors::{DiagCtxt, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; +use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; -use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::{select, DefiningAnchor}; @@ -818,7 +819,7 @@ impl<'tcx> InferCtxt<'tcx> { (0..table.len()) .map(|i| ty::EffectVid::from_usize(i)) - .filter(|&vid| table.probe_value(vid).is_none()) + .filter(|&vid| table.probe_value(vid).is_unknown()) .map(|v| { ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool) }) @@ -1236,7 +1237,8 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn var_for_effect(&self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { - let effect_vid = self.inner.borrow_mut().effect_unification_table().new_key(None).vid; + let effect_vid = + self.inner.borrow_mut().effect_unification_table().new_key(EffectVarValue::Unknown).vid; let ty = self .tcx .type_of(param.def_id) @@ -1416,8 +1418,8 @@ impl<'tcx> InferCtxt<'tcx> { } } - pub fn probe_effect_var(&self, vid: EffectVid) -> Option> { - self.inner.borrow_mut().effect_unification_table().probe_value(vid) + pub fn probe_effect_var(&self, vid: EffectVid) -> Option> { + self.inner.borrow_mut().effect_unification_table().probe_value(vid).known() } /// Attempts to resolve all type/region/const variables in @@ -1893,7 +1895,8 @@ impl<'a, 'tcx> TypeFolder> for ShallowResolver<'a, 'tcx> { .borrow_mut() .effect_unification_table() .probe_value(vid) - .map_or(ct, |val| val.as_const(self.infcx.tcx)), + .known() + .unwrap_or(ct), _ => ct, } } diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 1c120646f1f90..13c17ee1cd2b8 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -202,11 +202,7 @@ impl<'tcx> InferCtxt<'tcx> { ty::ConstKind::Infer(InferConst::EffectVar(a_vid)), ty::ConstKind::Infer(InferConst::EffectVar(b_vid)), ) => { - self.inner - .borrow_mut() - .effect_unification_table() - .unify_var_var(a_vid, b_vid) - .map_err(|a| effect_unification_error(self.tcx, relation.a_is_expected(), a))?; + self.inner.borrow_mut().effect_unification_table().union(a_vid, b_vid); return Ok(a); } @@ -233,19 +229,11 @@ impl<'tcx> InferCtxt<'tcx> { } (ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => { - return self.unify_effect_variable( - relation.a_is_expected(), - vid, - EffectVarValue::Const(b), - ); + return Ok(self.unify_effect_variable(vid, b)); } (_, ty::ConstKind::Infer(InferConst::EffectVar(vid))) => { - return self.unify_effect_variable( - !relation.a_is_expected(), - vid, - EffectVarValue::Const(a), - ); + return Ok(self.unify_effect_variable(vid, a)); } (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) @@ -366,18 +354,12 @@ impl<'tcx> InferCtxt<'tcx> { Ok(Ty::new_float(self.tcx, val)) } - fn unify_effect_variable( - &self, - vid_is_expected: bool, - vid: ty::EffectVid, - val: EffectVarValue<'tcx>, - ) -> RelateResult<'tcx, ty::Const<'tcx>> { + fn unify_effect_variable(&self, vid: ty::EffectVid, val: ty::Const<'tcx>) -> ty::Const<'tcx> { self.inner .borrow_mut() .effect_unification_table() - .unify_var_value(vid, Some(val)) - .map_err(|e| effect_unification_error(self.tcx, vid_is_expected, e))?; - Ok(val.as_const(self.tcx)) + .union_value(vid, EffectVarValue::Known(val)); + val } } @@ -579,11 +561,3 @@ fn float_unification_error<'tcx>( let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b)) } - -fn effect_unification_error<'tcx>( - _tcx: TyCtxt<'tcx>, - _a_is_expected: bool, - (_a, _b): (EffectVarValue<'tcx>, EffectVarValue<'tcx>), -) -> TypeError<'tcx> { - bug!("unexpected effect unification error") -} diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 959b09031277c..d5999331dfab6 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -237,14 +237,13 @@ impl<'tcx> TypeFolder> for EagerResolver<'_, 'tcx> { } ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool); - match self.infcx.probe_effect_var(vid) { - Some(c) => c.as_const(self.infcx.tcx), - None => ty::Const::new_infer( + self.infcx.probe_effect_var(vid).unwrap_or_else(|| { + ty::Const::new_infer( self.infcx.tcx, ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)), self.infcx.tcx.types.bool, - ), - } + ) + }) } _ => { if c.has_infer() { diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index c35799ef47f2b..63c0ebd5f6b79 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -194,33 +194,37 @@ impl<'tcx> UnifyValue for ConstVariableValue<'tcx> { /// values for the effect inference variable #[derive(Clone, Copy, Debug)] pub enum EffectVarValue<'tcx> { - /// The host effect is on, enabling access to syscalls, filesystem access, etc. - Host, - /// The host effect is off. Execution is restricted to const operations only. - NoHost, - Const(ty::Const<'tcx>), + Unknown, + Known(ty::Const<'tcx>), } impl<'tcx> EffectVarValue<'tcx> { - pub fn as_const(self, tcx: TyCtxt<'tcx>) -> ty::Const<'tcx> { + pub fn known(self) -> Option> { match self { - EffectVarValue::Host => tcx.consts.true_, - EffectVarValue::NoHost => tcx.consts.false_, - EffectVarValue::Const(c) => c, + EffectVarValue::Unknown => None, + EffectVarValue::Known(value) => Some(value), + } + } + + pub fn is_unknown(self) -> bool { + match self { + EffectVarValue::Unknown => true, + EffectVarValue::Known(_) => false, } } } impl<'tcx> UnifyValue for EffectVarValue<'tcx> { - type Error = (EffectVarValue<'tcx>, EffectVarValue<'tcx>); + type Error = NoError; fn unify_values(value1: &Self, value2: &Self) -> Result { - match (value1, value2) { - (EffectVarValue::Host, EffectVarValue::Host) => Ok(EffectVarValue::Host), - (EffectVarValue::NoHost, EffectVarValue::NoHost) => Ok(EffectVarValue::NoHost), - (EffectVarValue::NoHost | EffectVarValue::Host, _) - | (_, EffectVarValue::NoHost | EffectVarValue::Host) => Err((*value1, *value2)), - (EffectVarValue::Const(_), EffectVarValue::Const(_)) => { - bug!("equating two const variables, both of which have known values") + match (*value1, *value2) { + (EffectVarValue::Unknown, EffectVarValue::Unknown) => Ok(EffectVarValue::Unknown), + (EffectVarValue::Unknown, EffectVarValue::Known(val)) + | (EffectVarValue::Known(val), EffectVarValue::Unknown) => { + Ok(EffectVarValue::Known(val)) + } + (EffectVarValue::Known(_), EffectVarValue::Known(_)) => { + bug!("equating known inference variables: {value1:?} {value2:?}") } } } @@ -229,7 +233,7 @@ impl<'tcx> UnifyValue for EffectVarValue<'tcx> { #[derive(PartialEq, Copy, Clone, Debug)] pub struct EffectVidKey<'tcx> { pub vid: ty::EffectVid, - pub phantom: PhantomData>, + pub phantom: PhantomData>, } impl<'tcx> From for EffectVidKey<'tcx> { @@ -239,7 +243,7 @@ impl<'tcx> From for EffectVidKey<'tcx> { } impl<'tcx> UnifyKey for EffectVidKey<'tcx> { - type Value = Option>; + type Value = EffectVarValue<'tcx>; #[inline] fn index(&self) -> u32 { self.vid.as_u32() From 83738a9b1ce5e67687f04cf6ce3f8cc29cb92af7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 2 Feb 2024 08:36:46 +0000 Subject: [PATCH 563/676] Stop bailing out from compilation just because there were incoherent traits --- .../src/check/compare_impl_item.rs | 4 ++ .../rustc_hir_analysis/src/check/wfcheck.rs | 8 ++++ compiler/rustc_hir_analysis/src/lib.rs | 4 +- compiler/rustc_hir_typeck/src/callee.rs | 5 ++- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 18 ++++---- .../rustc_hir_typeck/src/method/confirm.rs | 6 ++- tests/ui/associated-consts/issue-105330.rs | 1 + .../ui/associated-consts/issue-105330.stderr | 12 ++++-- tests/ui/coherence/associated-type2.rs | 20 +++++++++ tests/ui/coherence/associated-type2.stderr | 12 ++++++ ...t-conflicts-with-specific-multidispatch.rs | 1 + ...nflicts-with-specific-multidispatch.stderr | 22 +++++++++- tests/ui/coherence/coherence-orphan.rs | 3 ++ tests/ui/coherence/coherence-orphan.stderr | 33 +++++++++++++-- tests/ui/coherence/deep-bad-copy-reason.rs | 5 +++ .../ui/coherence/deep-bad-copy-reason.stderr | 31 ++++++++++++-- .../occurs-check/opaques.next.stderr | 13 ++++-- tests/ui/coherence/occurs-check/opaques.rs | 1 + tests/ui/error-codes/E0117.rs | 1 + tests/ui/error-codes/E0117.stderr | 14 +++++-- tests/ui/error-codes/E0120.rs | 1 + tests/ui/error-codes/E0374.rs | 2 +- tests/ui/error-codes/E0374.stderr | 13 +++++- tests/ui/error-codes/E0375.rs | 2 +- tests/ui/error-codes/E0375.stderr | 30 +++++++++++++- tests/ui/issues/issue-67535.rs | 6 +-- tests/ui/issues/issue-67535.stderr | 41 ++++++++++++++++++- .../override-item-on-marker-trait.rs | 2 + .../override-item-on-marker-trait.stderr | 21 ++++++++-- ...n-default-items-drop-coherence.next.stderr | 11 ++++- ...ialization-default-items-drop-coherence.rs | 14 +++---- .../missing-bound-in-derive-copy-impl-3.fixed | 4 +- .../missing-bound-in-derive-copy-impl-3.rs | 2 +- ...missing-bound-in-derive-copy-impl-3.stderr | 21 +++++++++- .../missing-bound-in-derive-copy-impl.rs | 2 + .../missing-bound-in-derive-copy-impl.stderr | 37 ++++++++++++++++- tests/ui/traits/issue-50480.rs | 2 + tests/ui/traits/issue-50480.stderr | 28 ++++++++++--- tests/ui/traits/issue-78372.rs | 3 +- tests/ui/traits/issue-78372.stderr | 33 +++++++++++++-- .../trait_ref_is_knowable-norm-overflow.rs | 1 + ...trait_ref_is_knowable-norm-overflow.stderr | 24 +++++++++-- .../next-solver/issue-118950-root-region.rs | 1 + .../issue-118950-root-region.stderr | 12 ++++-- .../ui/typeck/typeck_type_placeholder_item.rs | 1 + .../typeck_type_placeholder_item.stderr | 37 ++++++++++------- 46 files changed, 473 insertions(+), 92 deletions(-) create mode 100644 tests/ui/coherence/associated-type2.rs create mode 100644 tests/ui/coherence/associated-type2.stderr diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 379c1154e5f26..d0683686d3812 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1990,6 +1990,10 @@ pub(super) fn check_type_bounds<'tcx>( impl_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure().coherent_trait(impl_trait_ref.def_id)?; + let param_env = tcx.param_env(impl_ty.def_id); debug!(?param_env); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 885cfbd0fe224..646a84b043c82 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1005,6 +1005,11 @@ fn check_associated_item( enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| { let item = tcx.associated_item(item_id); + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure() + .coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?; + let self_ty = match item.container { ty::TraitContainer => tcx.types.self_param, ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(), @@ -1291,6 +1296,9 @@ fn check_impl<'tcx>( // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity(); + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure().coherent_trait(trait_ref.def_id)?; let trait_ref = wfcx.normalize( ast_trait_ref.path.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 454cb97ac148b..2e85da98269cf 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -169,11 +169,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.sess.time("coherence_checking", || { // Check impls constrain their parameters - let mut res = + let res = tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); for &trait_def_id in tcx.all_local_trait_impls(()).keys() { - res = res.and(tcx.ensure().coherent_trait(trait_def_id)); + let _ = tcx.ensure().coherent_trait(trait_def_id); } // these queries are executed for side-effects (error reporting): res.and(tcx.ensure().crate_inherent_impls(())) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index b263c98553421..5805c71340309 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -41,7 +41,7 @@ pub fn check_legal_trait_for_method_call( receiver: Option, expr_span: Span, trait_id: DefId, -) { +) -> Result<(), ErrorGuaranteed> { if tcx.lang_items().drop_trait() == Some(trait_id) { let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) { errors::ExplicitDestructorCallSugg::Snippet { @@ -51,8 +51,9 @@ pub fn check_legal_trait_for_method_call( } else { errors::ExplicitDestructorCallSugg::Empty(span) }; - tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg }); + return Err(tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg })); } + tcx.coherent_trait(trait_id) } #[derive(Debug)] diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 60eb40bd8fe66..9935a215009a3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1105,13 +1105,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let container_id = assoc_item.container_id(tcx); debug!(?def_id, ?container, ?container_id); match container { - ty::TraitContainer => callee::check_legal_trait_for_method_call( - tcx, - path_span, - None, - span, - container_id, - ), + ty::TraitContainer => { + if let Err(e) = callee::check_legal_trait_for_method_call( + tcx, + path_span, + None, + span, + container_id, + ) { + self.set_tainted_by_errors(e); + } + } ty::ImplContainer => { if segments.len() == 1 { // `::assoc` will end up here, and so diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 6f18cc51b11c1..c8a235761dee8 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -630,13 +630,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) { // Disallow calls to the method `drop` defined in the `Drop` trait. if let Some(trait_def_id) = pick.item.trait_container(self.tcx) { - callee::check_legal_trait_for_method_call( + if let Err(e) = callee::check_legal_trait_for_method_call( self.tcx, self.span, Some(self.self_expr.span), self.call_expr.span, trait_def_id, - ) + ) { + self.set_tainted_by_errors(e); + } } } diff --git a/tests/ui/associated-consts/issue-105330.rs b/tests/ui/associated-consts/issue-105330.rs index 285e89cce4985..6c6dae864f340 100644 --- a/tests/ui/associated-consts/issue-105330.rs +++ b/tests/ui/associated-consts/issue-105330.rs @@ -14,5 +14,6 @@ fn foo>() { //~ ERROR E0658 fn main>() { //~^ ERROR E0658 + //~| ERROR E0131 foo::(); } diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr index 452367bed1201..b4c021d0f4fdc 100644 --- a/tests/ui/associated-consts/issue-105330.stderr +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -43,7 +43,13 @@ LL | impl TraitWAssocConst for impl Demo { | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error: aborting due to 5 previous errors +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/issue-105330.rs:15:8 + | +LL | fn main>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters + +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0404, E0562, E0658. -For more information about an error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0131, E0404, E0562, E0658. +For more information about an error, try `rustc --explain E0131`. diff --git a/tests/ui/coherence/associated-type2.rs b/tests/ui/coherence/associated-type2.rs new file mode 100644 index 0000000000000..2aadfb04af05d --- /dev/null +++ b/tests/ui/coherence/associated-type2.rs @@ -0,0 +1,20 @@ +//! A regression test for #120343. The overlap error was previously +//! silenced in coherence because projecting `<() as ToUnit>::Unit` +//! failed. Then then silenced the missing items error in the `ToUnit` +//! impl, causing us to not emit any errors and ICEing due to a +//! `span_delay_bug`. + +trait ToUnit { + type Unit; +} + +impl ToUnit for *const T {} +//~^ ERROR: not all trait items implemented + +trait Overlap {} + +impl Overlap for T {} + +impl Overlap<<*const T as ToUnit>::Unit> for T {} + +fn main() {} diff --git a/tests/ui/coherence/associated-type2.stderr b/tests/ui/coherence/associated-type2.stderr new file mode 100644 index 0000000000000..62d3d8b8ebd1c --- /dev/null +++ b/tests/ui/coherence/associated-type2.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `Unit` + --> $DIR/associated-type2.rs:11:1 + | +LL | type Unit; + | --------- `Unit` from trait +... +LL | impl ToUnit for *const T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Unit` in implementation + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs index 6a9db217373f9..cdec81271d090 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs @@ -22,6 +22,7 @@ struct MyType { impl MyTrait for MyType { //~^ ERROR E0119 fn get(&self) -> usize { (*self).clone() } + //~^ ERROR incompatible type } fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr index ddb7474c2899a..471dfe1cae79d 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr @@ -7,6 +7,24 @@ LL | impl MyTrait for T { LL | impl MyTrait for MyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` -error: aborting due to 1 previous error +error[E0053]: method `get` has an incompatible type for trait + --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:24:22 + | +LL | fn get(&self) -> usize { (*self).clone() } + | ^^^^^ + | | + | expected `MyType`, found `usize` + | help: change the output type to match the trait: `MyType` + | +note: type in trait + --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:8:22 + | +LL | fn get(&self) -> T; + | ^ + = note: expected signature `fn(&MyType) -> MyType` + found signature `fn(&MyType) -> usize` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0053, E0119. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/coherence/coherence-orphan.rs b/tests/ui/coherence/coherence-orphan.rs index bed782203af50..985cfe8716130 100644 --- a/tests/ui/coherence/coherence-orphan.rs +++ b/tests/ui/coherence/coherence-orphan.rs @@ -9,10 +9,13 @@ struct TheType; impl TheTrait for isize { } //~^ ERROR E0117 +//~| ERROR not all trait items implemented impl TheTrait for isize { } +//~^ ERROR not all trait items implemented impl TheTrait for TheType { } +//~^ ERROR not all trait items implemented impl !Send for Vec { } //~ ERROR E0117 //~^ WARNING diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr index 9ec1d0dc32aa4..78fad837647b4 100644 --- a/tests/ui/coherence/coherence-orphan.stderr +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -11,7 +11,7 @@ LL | impl TheTrait for isize { } = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/coherence-orphan.rs:17:1 + --> $DIR/coherence-orphan.rs:20:1 | LL | impl !Send for Vec { } | ^^^^^^^^^^^^^^^---------- @@ -22,7 +22,7 @@ LL | impl !Send for Vec { } = note: define and implement a trait or new type instead warning: cross-crate traits with a default impl, like `Send`, should not be specialized - --> $DIR/coherence-orphan.rs:17:1 + --> $DIR/coherence-orphan.rs:20:1 | LL | impl !Send for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,6 +34,31 @@ note: try using the same sequence of generic parameters as the struct definition --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = note: `#[warn(suspicious_auto_trait_impls)]` on by default -error: aborting due to 2 previous errors; 1 warning emitted +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:10:1 + | +LL | impl TheTrait for isize { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:14:1 + | +LL | impl TheTrait for isize { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:17:1 + | +LL | impl TheTrait for TheType { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error: aborting due to 5 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0046, E0117. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/coherence/deep-bad-copy-reason.rs b/tests/ui/coherence/deep-bad-copy-reason.rs index 97fd3f719bfbf..f1c2698bad5cc 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.rs +++ b/tests/ui/coherence/deep-bad-copy-reason.rs @@ -5,12 +5,15 @@ extern "Rust" { } pub struct ListS { + //~^ NOTE: required because it appears within the type len: usize, data: [T; 0], opaque: OpaqueListContents, } pub struct Interned<'a, T>(&'a T); +//~^ NOTE: required by an implicit `Sized` +//~| NOTE: required by the implicit `Sized` impl<'a, T> Clone for Interned<'a, T> { fn clone(&self) -> Self { @@ -23,6 +26,8 @@ impl<'a, T> Copy for Interned<'a, T> {} pub struct List<'tcx, T>(Interned<'tcx, ListS>); //~^ NOTE this field does not implement `Copy` //~| NOTE the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` +//~| NOTE: doesn't have a size known at compile-time +//~| ERROR: cannot be known at compilation time impl<'tcx, T> Clone for List<'tcx, T> { fn clone(&self) -> Self { diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr index e79abe35597d4..fe5ae9b08b4b9 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.stderr +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/deep-bad-copy-reason.rs:33:24 + --> $DIR/deep-bad-copy-reason.rs:38:24 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ------------------------ this field does not implement `Copy` @@ -8,11 +8,34 @@ LL | impl<'tcx, T> Copy for List<'tcx, T> {} | ^^^^^^^^^^^^^ | note: the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` - --> $DIR/deep-bad-copy-reason.rs:23:26 + --> $DIR/deep-bad-copy-reason.rs:26:26 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0277]: the size for values of type `OpaqueListContents` cannot be known at compilation time + --> $DIR/deep-bad-copy-reason.rs:26:26 + | +LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `ListS`, the trait `Sized` is not implemented for `OpaqueListContents`, which is required by `ListS: Sized` +note: required because it appears within the type `ListS` + --> $DIR/deep-bad-copy-reason.rs:7:12 + | +LL | pub struct ListS { + | ^^^^^ +note: required by an implicit `Sized` bound in `Interned` + --> $DIR/deep-bad-copy-reason.rs:14:25 + | +LL | pub struct Interned<'a, T>(&'a T); + | ^ required by the implicit `Sized` requirement on this type parameter in `Interned` +help: consider relaxing the implicit `Sized` restriction + | +LL | pub struct Interned<'a, T: ?Sized>(&'a T); + | ++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 428ee902ea528..4ad8257d2c14b 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait>` for type `Alias<_>` - --> $DIR/opaques.rs:29:1 + --> $DIR/opaques.rs:30:1 | LL | impl Trait for T { | ---------------------- first implementation here @@ -7,6 +7,13 @@ LL | impl Trait for T { LL | impl Trait for defining_scope::Alias { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias<_>` -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/opaques.rs:13:20 + | +LL | pub fn cast(x: Container, T>) -> Container { + | ^ cannot infer type for struct `Container, T>` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0282. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index 2fa9dcebfdec4..73cd42bf3f25d 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -11,6 +11,7 @@ mod defining_scope { pub type Alias = impl Sized; pub fn cast(x: Container, T>) -> Container { + //[next]~^ ERROR type annotations needed x } } diff --git a/tests/ui/error-codes/E0117.rs b/tests/ui/error-codes/E0117.rs index 406d24e366614..32b9863806c04 100644 --- a/tests/ui/error-codes/E0117.rs +++ b/tests/ui/error-codes/E0117.rs @@ -1,4 +1,5 @@ impl Drop for u32 {} //~ ERROR E0117 //~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions +//~| ERROR not all trait items implemented fn main() {} diff --git a/tests/ui/error-codes/E0117.stderr b/tests/ui/error-codes/E0117.stderr index f144aa9f72c13..058a64b20d171 100644 --- a/tests/ui/error-codes/E0117.stderr +++ b/tests/ui/error-codes/E0117.stderr @@ -15,7 +15,15 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums, LL | impl Drop for u32 {} | ^^^ must be a struct, enum, or union in the current crate -error: aborting due to 2 previous errors +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/E0117.rs:1:1 + | +LL | impl Drop for u32 {} + | ^^^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `fn drop(&mut self) { todo!() }` + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0117, E0120. -For more information about an error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0046, E0117, E0120. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/error-codes/E0120.rs b/tests/ui/error-codes/E0120.rs index a0a301a06e2ed..35f544fddfbfc 100644 --- a/tests/ui/error-codes/E0120.rs +++ b/tests/ui/error-codes/E0120.rs @@ -3,6 +3,7 @@ trait MyTrait { fn foo() {} } impl Drop for dyn MyTrait { //~^ ERROR E0120 fn drop(&mut self) {} + } fn main() {} diff --git a/tests/ui/error-codes/E0374.rs b/tests/ui/error-codes/E0374.rs index 41fcedc328df1..47b9bea978e40 100644 --- a/tests/ui/error-codes/E0374.rs +++ b/tests/ui/error-codes/E0374.rs @@ -1,7 +1,7 @@ #![feature(coerce_unsized)] use std::ops::CoerceUnsized; -struct Foo { +struct Foo { //~ ERROR `T` is never used a: i32, } diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr index 148fa1348ab66..77f351b28ef24 100644 --- a/tests/ui/error-codes/E0374.stderr +++ b/tests/ui/error-codes/E0374.stderr @@ -7,6 +7,15 @@ LL | | where T: CoerceUnsized {} | = note: expected a single field to be coerced, none found -error: aborting due to 1 previous error +error[E0392]: type parameter `T` is never used + --> $DIR/E0374.rs:4:12 + | +LL | struct Foo { + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0374`. +Some errors have detailed explanations: E0374, E0392. +For more information about an error, try `rustc --explain E0374`. diff --git a/tests/ui/error-codes/E0375.rs b/tests/ui/error-codes/E0375.rs index 0c03a8761df01..eaf99dd384230 100644 --- a/tests/ui/error-codes/E0375.rs +++ b/tests/ui/error-codes/E0375.rs @@ -3,7 +3,7 @@ use std::ops::CoerceUnsized; struct Foo { a: i32, - b: T, + b: T, //~ ERROR E0277 c: U, } diff --git a/tests/ui/error-codes/E0375.stderr b/tests/ui/error-codes/E0375.stderr index 0a5e4128ae9d7..d5340022d68ce 100644 --- a/tests/ui/error-codes/E0375.stderr +++ b/tests/ui/error-codes/E0375.stderr @@ -7,6 +7,32 @@ LL | impl CoerceUnsized> for Foo {} = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) -error: aborting due to 1 previous error +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/E0375.rs:6:8 + | +LL | struct Foo { + | - this type parameter needs to be `Sized` +LL | a: i32, +LL | b: T, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct Foo { +LL + struct Foo { + | +help: borrowed types always have a statically known size + | +LL | b: &T, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | b: Box, + | ++++ + + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0375`. +Some errors have detailed explanations: E0277, E0375. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-67535.rs b/tests/ui/issues/issue-67535.rs index 24f50621310f1..153b95a167434 100644 --- a/tests/ui/issues/issue-67535.rs +++ b/tests/ui/issues/issue-67535.rs @@ -2,21 +2,21 @@ fn main() {} impl std::ops::AddAssign for () { //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types - fn add_assign(&self, other: ()) -> () { + fn add_assign(&self, other: ()) -> () { //~ ERROR incompatible type () } } impl std::ops::AddAssign for [(); 1] { //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types - fn add_assign(&self, other: [(); 1]) -> [(); 1] { + fn add_assign(&self, other: [(); 1]) -> [(); 1] { //~ ERROR incompatible type [()] } } impl std::ops::AddAssign for &[u8] { //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types - fn add_assign(&self, other: &[u8]) -> &[u8] { + fn add_assign(&self, other: &[u8]) -> &[u8] { //~ ERROR incompatible type self } } diff --git a/tests/ui/issues/issue-67535.stderr b/tests/ui/issues/issue-67535.stderr index 4d7a02a50969f..c8bde2cb88c77 100644 --- a/tests/ui/issues/issue-67535.stderr +++ b/tests/ui/issues/issue-67535.stderr @@ -34,6 +34,43 @@ LL | impl std::ops::AddAssign for &[u8] { | = note: define and implement a trait or new type instead -error: aborting due to 3 previous errors +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:5:19 + | +LL | fn add_assign(&self, other: ()) -> () { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut (), ())` + found signature `fn(&(), ())` + +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:12:19 + | +LL | fn add_assign(&self, other: [(); 1]) -> [(); 1] { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut _, _)` + found signature `fn(&_, _) -> [(); 1]` + +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:19:19 + | +LL | fn add_assign(&self, other: &[u8]) -> &[u8] { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut &_, &_)` + found signature `fn(&&_, &_) -> &[u8]` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0053, E0117. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs b/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs index 5376fc89d4f4a..d91a8055aa16d 100644 --- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs @@ -3,7 +3,9 @@ #[marker] trait Marker { const N: usize = 0; + //~^ ERROR marker traits cannot have associated items fn do_something() {} + //~^ ERROR marker traits cannot have associated items } struct OverrideConst; diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr index 1d30c6d566742..92a54cff7f5fa 100644 --- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr @@ -1,15 +1,28 @@ error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:10:1 + --> $DIR/override-item-on-marker-trait.rs:12:1 | LL | impl Marker for OverrideConst { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:16:1 + --> $DIR/override-item-on-marker-trait.rs:18:1 | LL | impl Marker for OverrideFn { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0714]: marker traits cannot have associated items + --> $DIR/override-item-on-marker-trait.rs:5:5 + | +LL | const N: usize = 0; + | ^^^^^^^^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/override-item-on-marker-trait.rs:7:5 + | +LL | fn do_something() {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0715`. +Some errors have detailed explanations: E0714, E0715. +For more information about an error, try `rustc --explain E0714`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr index e9498a003179b..78d77a78e0eef 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -7,6 +7,13 @@ LL | impl Overlap for u32 { LL | impl Overlap for ::Id { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/specialization-default-items-drop-coherence.rs:18:23 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `::Id` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0282. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs index 37903c210714e..87eb5d90def70 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -11,25 +11,25 @@ #![allow(incomplete_features)] trait Default { - type Id; + type Id; } impl Default for T { - default type Id = T; + default type Id = T; //[next]~ ERROR type annotations needed } trait Overlap { - type Assoc; + type Assoc; } impl Overlap for u32 { - type Assoc = usize; + type Assoc = usize; } impl Overlap for ::Id { - //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` - //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` - type Assoc = Box; + //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` + //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` + type Assoc = Box; } fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed index 47b35b412c037..53476ee8c5936 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -8,8 +8,8 @@ pub struct Vector2{ } #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ - pub loc: Vector2, +pub struct AABB{ + pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` pub size: Vector2 } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs index 771e9105c6211..08c4f344e4ef0 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -9,7 +9,7 @@ pub struct Vector2{ #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB{ - pub loc: Vector2, + pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` pub size: Vector2 } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index ed1bde5f83e53..bfb96b4076b0f 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -18,6 +18,23 @@ help: consider further restricting this bound LL | pub struct AABB{ | +++++++ -error: aborting due to 1 previous error +error[E0277]: `K` doesn't implement `Debug` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:5:23 + | +LL | pub struct Vector2{ + | ^^^^^ required by this bound in `Vector2` +help: consider further restricting this bound + | +LL | pub struct AABB{ + | +++++++++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs index 9c7b7ba099c43..2f1ebc1f133d6 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -9,6 +9,8 @@ pub struct Vector2{ #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB{ pub loc: Vector2, + //~^ ERROR doesn't implement `Debug` + //~| ERROR `K: Copy` is not satisfied pub size: Vector2 } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 03db737fa8761..f3213e1a4c818 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -18,6 +18,39 @@ help: consider restricting type parameter `K` LL | pub struct AABB{ | +++++++ -error: aborting due to 1 previous error +error[E0277]: `K` doesn't implement `Debug` + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:23 + | +LL | pub struct Vector2{ + | ^^^^^ required by this bound in `Vector2` +help: consider restricting type parameter `K` + | +LL | pub struct AABB{ + | +++++++++++++++++ + +error[E0277]: the trait bound `K: Copy` is not satisfied + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ the trait `Copy` is not implemented for `K` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:31 + | +LL | pub struct Vector2{ + | ^^^^ required by this bound in `Vector2` +help: consider restricting type parameter `K` + | +LL | pub struct AABB{ + | +++++++++++++++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs index 683a85a32c1c6..cc7ea32eb3a5c 100644 --- a/tests/ui/traits/issue-50480.rs +++ b/tests/ui/traits/issue-50480.rs @@ -5,11 +5,13 @@ struct Foo(N, NotDefined, ::Item, Vec, String); //~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR cannot find type `N` in this scope +//~| ERROR `i32` is not an iterator #[derive(Clone, Copy)] //~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar(T, N, NotDefined, ::Item, Vec, String); //~^ ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope +//~| ERROR `i32` is not an iterator fn main() {} diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 4f72db60a1647..68d3d5c80d0d2 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -38,7 +38,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, St | ++++++++++++ error[E0412]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:11:18 + --> $DIR/issue-50480.rs:12:18 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | - ^ @@ -55,7 +55,7 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, Strin | +++ error[E0412]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:11:21 + --> $DIR/issue-50480.rs:12:21 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope @@ -74,7 +74,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:9:17 + --> $DIR/issue-50480.rs:10:17 | LL | #[derive(Clone, Copy)] | ^^^^ @@ -86,7 +86,25 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 8 previous errors +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:3:27 + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = 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` + +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:12:33 + | +LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = 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` + +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0204, E0412. +Some errors have detailed explanations: E0204, E0277, E0412. For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs index 92f9f4b467a97..143325c097c13 100644 --- a/tests/ui/traits/issue-78372.rs +++ b/tests/ui/traits/issue-78372.rs @@ -6,8 +6,9 @@ impl DispatchFromDyn> for T {} //~ ERROR cannot find type `U` //~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures trait Foo: X {} trait X { - fn foo(self: Smaht); + fn foo(self: Smaht); //~ ERROR: invalid `self` } trait Marker {} impl Marker for dyn Foo {} +//~^ ERROR cannot be made into an object fn main() {} diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 44a62988daf37..edb07957c445c 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -61,7 +61,34 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion LL | impl DispatchFromDyn> for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/issue-78372.rs:12:17 + | +LL | fn foo(self: Smaht); + | -------------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | impl Marker for dyn Foo {} + | ^^^^^^^ `Foo` 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 + --> $DIR/issue-78372.rs:9:18 + | +LL | trait Foo: X {} + | --- this trait cannot be made into an object... +LL | trait X { +LL | fn foo(self: Smaht); + | ^^^^^^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on -Some errors have detailed explanations: E0378, E0412, E0658. -For more information about an error, try `rustc --explain E0378`. +error[E0307]: invalid `self` parameter type: Smaht + --> $DIR/issue-78372.rs:9:18 + | +LL | fn foo(self: Smaht); + | ^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin