From 2036aea18e9a525fa7180240c657944fc6838035 Mon Sep 17 00:00:00 2001 From: Audun Halland Date: Sun, 10 Jul 2022 11:27:36 +0200 Subject: [PATCH 01/21] Determine match_has_guard from candidates instead of looking up thir table again --- compiler/rustc_mir_build/src/build/matches/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 1628f1a4b850b..790e4f6877595 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -170,7 +170,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms); - let match_has_guard = arms.iter().copied().any(|arm| self.thir[arm].guard.is_some()); + let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard); let mut candidates = arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::>(); From 18a21e13b49320bc20836d5d20da82375fac2bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 6 Aug 2022 00:00:00 +0000 Subject: [PATCH 02/21] Remove duplicated temporaries creating during box derefs elaboration Temporaries created with `MirPatch::new_temp` will be declared after patch application. Remove manually created duplicate declarations. Removing duplicates exposes another issue. Visitor elaborates terminator twice and attempts to access new, but not yet available, local declarations. Remove duplicated call to `visit_terminator`. --- compiler/rustc_mir_transform/src/elaborate_box_derefs.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 44e3945d6fc89..f79d2afc0c6be 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -70,7 +70,6 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did); let ptr_local = self.patch.new_temp(ptr_ty, source_info.span); - self.local_decls.push(LocalDecl::new(ptr_ty, source_info.span)); self.patch.add_statement(location, StatementKind::StorageLive(ptr_local)); @@ -125,13 +124,6 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs { index += 1; } - if let Some(terminator) = terminator - && !matches!(terminator.kind, TerminatorKind::Yield{..}) - { - let location = Location { block, statement_index: index }; - visitor.visit_terminator(terminator, location); - } - let location = Location { block, statement_index: index }; match terminator { // yielding into a box is handled when lowering generators From 7d2131a2048521ee1dfc41a12b2f5007effc1f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 6 Aug 2022 00:00:00 +0000 Subject: [PATCH 03/21] ./x.py test --bless --- .../const_prop/boxes.main.ConstProp.diff | 2 -- ...line_into_box_place.main.Inline.32bit.diff | 23 +++++++++---------- ...line_into_box_place.main.Inline.64bit.diff | 23 +++++++++---------- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff index f2d4bee1bf94d..73fdf14049896 100644 --- a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff @@ -12,8 +12,6 @@ let mut _7: std::boxed::Box; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 let mut _8: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 let mut _9: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - let mut _10: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - let mut _11: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 scope 1 { debug x => _1; // in scope 1 at $DIR/boxes.rs:+1:9: +1:10 } diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index deaba70e082ed..5dfcd2d54ca27 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -10,15 +10,14 @@ let mut _5: std::boxed::Box>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 let mut _7: *const std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _8: *const std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 -+ let mut _9: &mut std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 ++ let mut _8: &mut std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 scope 1 { debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:+1:9: +1:11 } scope 2 { } + scope 3 (inlined Vec::::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ let mut _10: alloc::raw_vec::RawVec; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ let mut _9: alloc::raw_vec::RawVec; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + } bb0: { @@ -37,10 +36,10 @@ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 _7 = (((_5.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 - (*_7) = Vec::::new() -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ StorageLive(_9); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ _9 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ StorageLive(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ _10 = const alloc::raw_vec::RawVec::::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ StorageLive(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 ++ _8 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 ++ StorageLive(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ _9 = const alloc::raw_vec::RawVec::::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 - // + user_ty: UserType(1) @@ -51,11 +50,11 @@ + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) + // + literal: Const { ty: alloc::raw_vec::RawVec, val: Unevaluated(alloc::raw_vec::RawVec::::NEW, [u32], None) } -+ Deinit((*_9)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ ((*_9).0: alloc::raw_vec::RawVec) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ ((*_9).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ StorageDead(_9); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 ++ Deinit((*_8)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ ((*_8).0: alloc::raw_vec::RawVec) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ StorageDead(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ StorageDead(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index deaba70e082ed..5dfcd2d54ca27 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -10,15 +10,14 @@ let mut _5: std::boxed::Box>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 let mut _7: *const std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 - let mut _8: *const std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 -+ let mut _9: &mut std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 ++ let mut _8: &mut std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 scope 1 { debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:+1:9: +1:11 } scope 2 { } + scope 3 (inlined Vec::::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ let mut _10: alloc::raw_vec::RawVec; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ let mut _9: alloc::raw_vec::RawVec; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + } bb0: { @@ -37,10 +36,10 @@ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 _7 = (((_5.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 - (*_7) = Vec::::new() -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ StorageLive(_9); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ _9 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 -+ StorageLive(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ _10 = const alloc::raw_vec::RawVec::::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ StorageLive(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 ++ _8 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 ++ StorageLive(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ _9 = const alloc::raw_vec::RawVec::::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 - // + user_ty: UserType(1) @@ -51,11 +50,11 @@ + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) + // + literal: Const { ty: alloc::raw_vec::RawVec, val: Unevaluated(alloc::raw_vec::RawVec::::NEW, [u32], None) } -+ Deinit((*_9)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ ((*_9).0: alloc::raw_vec::RawVec) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ ((*_9).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ StorageDead(_9); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 ++ Deinit((*_8)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ ((*_8).0: alloc::raw_vec::RawVec) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ StorageDead(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ StorageDead(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43 _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43 StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43 From 013986be1bcfbfd9cedddf22dfd9584ccdb7ee6e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 8 Aug 2022 13:27:09 -0700 Subject: [PATCH 04/21] linux: Use `pthread_setname_np` instead of `prctl` This function is available on Linux since glibc 2.12, musl 1.1.16, and uClibc 1.0.20. The main advantage over `prctl` is that it properly represents the pointer argument, rather than a multi-purpose `long`, so we're better representing strict provenance (#95496). --- library/std/src/sys/unix/thread.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 36a3fa6023bfb..7db3065dee083 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -116,11 +116,9 @@ impl Thread { debug_assert_eq!(ret, 0); } - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(target_os = "android")] pub fn set_name(name: &CStr) { const PR_SET_NAME: libc::c_int = 15; - // pthread wrapper only appeared in glibc 2.12, so we use syscall - // directly. unsafe { libc::prctl( PR_SET_NAME, @@ -132,6 +130,14 @@ impl Thread { } } + #[cfg(target_os = "linux")] + pub fn set_name(name: &CStr) { + unsafe { + // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20. + libc::pthread_setname_np(libc::pthread_self(), name.as_ptr()); + } + } + #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))] pub fn set_name(name: &CStr) { unsafe { From 574ba831d426b7c72279906a3dfd38ae5af53dce Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 10 Aug 2022 09:47:59 +1000 Subject: [PATCH 05/21] Avoid repeating qualifiers on `static_assert_size` calls. Some of these don't need a `use` statement because there is already a `#[macro_use] extern crate rustc_data_structures` item in the crate. --- compiler/rustc_ast/src/ast.rs | 35 ++++++++++--------- .../rustc_const_eval/src/interpret/operand.rs | 9 ++--- .../rustc_const_eval/src/interpret/place.rs | 11 +++--- compiler/rustc_hir/src/hir.rs | 24 ++++++------- compiler/rustc_middle/src/thir.rs | 8 ++--- src/librustdoc/clean/types.rs | 19 +++++----- 6 files changed, 55 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 870a7c0be33dc..5e8fd508f56fb 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3030,22 +3030,23 @@ pub type ForeignItem = Item; #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { use super::*; + use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. - rustc_data_structures::static_assert_size!(AssocItemKind, 72); - rustc_data_structures::static_assert_size!(Attribute, 152); - rustc_data_structures::static_assert_size!(Block, 48); - rustc_data_structures::static_assert_size!(Expr, 104); - rustc_data_structures::static_assert_size!(Fn, 192); - rustc_data_structures::static_assert_size!(ForeignItemKind, 72); - rustc_data_structures::static_assert_size!(GenericBound, 88); - rustc_data_structures::static_assert_size!(Generics, 72); - rustc_data_structures::static_assert_size!(Impl, 200); - rustc_data_structures::static_assert_size!(Item, 200); - rustc_data_structures::static_assert_size!(ItemKind, 112); - rustc_data_structures::static_assert_size!(Lit, 48); - rustc_data_structures::static_assert_size!(Pat, 120); - rustc_data_structures::static_assert_size!(Path, 40); - rustc_data_structures::static_assert_size!(PathSegment, 24); - rustc_data_structures::static_assert_size!(Stmt, 32); - rustc_data_structures::static_assert_size!(Ty, 96); + static_assert_size!(AssocItemKind, 72); + static_assert_size!(Attribute, 152); + static_assert_size!(Block, 48); + static_assert_size!(Expr, 104); + static_assert_size!(Fn, 192); + static_assert_size!(ForeignItemKind, 72); + static_assert_size!(GenericBound, 88); + static_assert_size!(Generics, 72); + static_assert_size!(Impl, 200); + static_assert_size!(Item, 200); + static_assert_size!(ItemKind, 112); + static_assert_size!(Lit, 48); + static_assert_size!(Pat, 120); + static_assert_size!(Path, 40); + static_assert_size!(PathSegment, 24); + static_assert_size!(Stmt, 32); + static_assert_size!(Ty, 96); } diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 94ba62c160c98..fe80a55dfd28c 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -823,9 +823,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { use super::*; + use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. - rustc_data_structures::static_assert_size!(Immediate, 56); - rustc_data_structures::static_assert_size!(ImmTy<'_>, 72); - rustc_data_structures::static_assert_size!(Operand, 64); - rustc_data_structures::static_assert_size!(OpTy<'_>, 88); + static_assert_size!(Immediate, 56); + static_assert_size!(ImmTy<'_>, 72); + static_assert_size!(Operand, 64); + static_assert_size!(OpTy<'_>, 88); } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index f4571a1ca3d8a..97fe23cb5bcf3 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -891,10 +891,11 @@ where #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { use super::*; + use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. - rustc_data_structures::static_assert_size!(MemPlaceMeta, 24); - rustc_data_structures::static_assert_size!(MemPlace, 40); - rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64); - rustc_data_structures::static_assert_size!(Place, 48); - rustc_data_structures::static_assert_size!(PlaceTy<'_>, 72); + static_assert_size!(MemPlaceMeta, 24); + static_assert_size!(MemPlace, 40); + static_assert_size!(MPlaceTy<'_>, 64); + static_assert_size!(Place, 48); + static_assert_size!(PlaceTy<'_>, 72); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 617433a9803d5..7a87a3e488260 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3491,16 +3491,16 @@ impl<'hir> Node<'hir> { mod size_asserts { use super::*; // These are in alphabetical order, which is easy to maintain. - rustc_data_structures::static_assert_size!(Block<'static>, 48); - rustc_data_structures::static_assert_size!(Expr<'static>, 56); - rustc_data_structures::static_assert_size!(ForeignItem<'static>, 72); - rustc_data_structures::static_assert_size!(GenericBound<'_>, 48); - rustc_data_structures::static_assert_size!(Generics<'static>, 56); - rustc_data_structures::static_assert_size!(ImplItem<'static>, 88); - rustc_data_structures::static_assert_size!(Impl<'static>, 80); - rustc_data_structures::static_assert_size!(Item<'static>, 80); - rustc_data_structures::static_assert_size!(Pat<'static>, 88); - rustc_data_structures::static_assert_size!(QPath<'static>, 24); - rustc_data_structures::static_assert_size!(TraitItem<'static>, 96); - rustc_data_structures::static_assert_size!(Ty<'static>, 72); + static_assert_size!(Block<'static>, 48); + static_assert_size!(Expr<'static>, 56); + static_assert_size!(ForeignItem<'static>, 72); + static_assert_size!(GenericBound<'_>, 48); + static_assert_size!(Generics<'static>, 56); + static_assert_size!(ImplItem<'static>, 88); + static_assert_size!(Impl<'static>, 80); + static_assert_size!(Item<'static>, 80); + static_assert_size!(Pat<'static>, 88); + static_assert_size!(QPath<'static>, 24); + static_assert_size!(TraitItem<'static>, 96); + static_assert_size!(Ty<'static>, 72); } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index b856af1d8f835..5e26a52900eaf 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -814,8 +814,8 @@ impl<'tcx> fmt::Display for Pat<'tcx> { mod size_asserts { use super::*; // These are in alphabetical order, which is easy to maintain. - rustc_data_structures::static_assert_size!(Block, 56); - rustc_data_structures::static_assert_size!(Expr<'_>, 104); - rustc_data_structures::static_assert_size!(Pat<'_>, 24); - rustc_data_structures::static_assert_size!(Stmt<'_>, 120); + static_assert_size!(Block, 56); + static_assert_size!(Expr<'_>, 104); + static_assert_size!(Pat<'_>, 24); + static_assert_size!(Stmt<'_>, 120); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 0e6de842cc267..91d5758077c94 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2495,14 +2495,15 @@ impl SubstParam { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { use super::*; + use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. - rustc_data_structures::static_assert_size!(Crate, 72); // frequently moved by-value - rustc_data_structures::static_assert_size!(DocFragment, 32); - rustc_data_structures::static_assert_size!(GenericArg, 80); - rustc_data_structures::static_assert_size!(GenericArgs, 32); - rustc_data_structures::static_assert_size!(GenericParamDef, 56); - rustc_data_structures::static_assert_size!(Item, 56); - rustc_data_structures::static_assert_size!(ItemKind, 112); - rustc_data_structures::static_assert_size!(PathSegment, 40); - rustc_data_structures::static_assert_size!(Type, 72); + static_assert_size!(Crate, 72); // frequently moved by-value + static_assert_size!(DocFragment, 32); + static_assert_size!(GenericArg, 80); + static_assert_size!(GenericArgs, 32); + static_assert_size!(GenericParamDef, 56); + static_assert_size!(Item, 56); + static_assert_size!(ItemKind, 112); + static_assert_size!(PathSegment, 40); + static_assert_size!(Type, 72); } From 0658e8cbcaa6f5d3952a0958ab7657fc8bba32d9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 10 Aug 2022 10:06:38 +1000 Subject: [PATCH 06/21] Add a couple more AST node size assertions. --- compiler/rustc_ast/src/ast.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5e8fd508f56fb..28862dbb2678b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3032,11 +3032,13 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. + static_assert_size!(AssocItem, 160); static_assert_size!(AssocItemKind, 72); static_assert_size!(Attribute, 152); static_assert_size!(Block, 48); static_assert_size!(Expr, 104); static_assert_size!(Fn, 192); + static_assert_size!(ForeignItem, 160); static_assert_size!(ForeignItemKind, 72); static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 72); From a2b6744af03e315587626e9faa34bfaf3b913012 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 10 Aug 2022 03:39:41 +0000 Subject: [PATCH 07/21] Use &mut Diagnostic instead of &mut DiagnosticBuilder unless needed --- compiler/rustc_ast_passes/src/ast_validation.rs | 8 +++----- .../src/diagnostics/conflict_errors.rs | 9 ++------- .../rustc_borrowck/src/diagnostics/region_errors.rs | 2 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 8 ++------ compiler/rustc_parse/src/parser/diagnostics.rs | 8 ++++---- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 6 +++--- compiler/rustc_typeck/src/astconv/mod.rs | 13 +++++-------- compiler/rustc_typeck/src/check/check.rs | 4 +--- compiler/rustc_typeck/src/check/coercion.rs | 4 ++-- compiler/rustc_typeck/src/check/expr.rs | 11 +++++------ compiler/rustc_typeck/src/check/fn_ctxt/checks.rs | 2 +- compiler/rustc_typeck/src/check/method/suggest.rs | 8 ++++---- compiler/rustc_typeck/src/check/mod.rs | 9 ++------- compiler/rustc_typeck/src/check/op.rs | 2 +- 15 files changed, 37 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 60560b1c00e25..d94f8a9af884b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -13,9 +13,7 @@ use rustc_ast::walk_list; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{ - error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, -}; +use rustc_errors::{error_code, pluralize, struct_span_err, Applicability, Diagnostic}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, @@ -477,7 +475,7 @@ impl<'a> AstValidator<'a> { ctx: &str, msg: &str, sugg: &str, - help: impl FnOnce(&mut DiagnosticBuilder<'_, ErrorGuaranteed>), + help: impl FnOnce(&mut Diagnostic), ) { let source_map = self.session.source_map(); let end = source_map.end_point(sp); @@ -1196,7 +1194,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let msg = "free function without a body"; let ext = sig.header.ext; - let f = |e: &mut DiagnosticBuilder<'_, _>| { + let f = |e: &mut Diagnostic| { if let Extern::Implicit(start_span) | Extern::Explicit(_, start_span) = &ext { let start_suggestion = if let Extern::Explicit(abi, _) = ext { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8bc8964bbd7cc..84a0d4ba7ba10 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -451,7 +451,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn suggest_borrow_fn_like( &self, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut Diagnostic, ty: Ty<'tcx>, move_sites: &[MoveSite], value_name: &str, @@ -526,12 +526,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { true } - fn suggest_adding_copy_bounds( - &self, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, - ty: Ty<'tcx>, - span: Span, - ) { + fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { let tcx = self.infcx.tcx; let generics = tcx.generics_of(self.mir_def_id()); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 176090c3b7a14..bd3a2a3d69496 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -783,7 +783,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn maybe_suggest_constrain_dyn_trait_impl( &self, - diag: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + diag: &mut Diagnostic, f: Region<'tcx>, o: Region<'tcx>, category: &ConstraintCategory<'tcx>, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index f7e1575afbf42..e009e4f7c68d0 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -14,7 +14,7 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_feature::Features; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, @@ -608,11 +608,7 @@ enum ExplainDocComment { }, } -fn annotate_doc_comment( - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, - sm: &SourceMap, - span: Span, -) { +fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) { if let Ok(src) = sm.span_to_snippet(span) { if src.starts_with("///") || src.starts_with("/**") { err.subdiagnostic(ExplainDocComment::Outer { span }); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a2155ac1d1ad4..f4c6b33a52924 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -19,7 +19,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, }; -use rustc_errors::{pluralize, struct_span_err, Diagnostic, EmissionGuarantee, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, Ident}; @@ -228,13 +228,13 @@ struct MultiSugg { } impl MultiSugg { - fn emit(self, err: &mut DiagnosticBuilder<'_, G>) { + fn emit(self, err: &mut Diagnostic) { err.multipart_suggestion(&self.msg, self.patches, self.applicability); } /// Overrides individual messages and applicabilities. - fn emit_many( - err: &mut DiagnosticBuilder<'_, G>, + fn emit_many( + err: &mut Diagnostic, msg: &str, applicability: Applicability, suggestions: impl Iterator, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e473f4d30cf09..7dda3428bd7ae 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -859,7 +859,7 @@ impl<'a> Parser<'a> { ); let mut err = self.struct_span_err(span, &msg); - let suggest_parens = |err: &mut DiagnosticBuilder<'_, _>| { + let suggest_parens = |err: &mut Diagnostic| { let suggestions = vec![ (span.shrink_to_lo(), "(".to_string()), (span.shrink_to_hi(), ")".to_string()), diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2b1f2b88ec445..cb133841bca5a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2021,9 +2021,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn suggest_introducing_lifetime( &self, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut Diagnostic, name: Option<&str>, - suggest: impl Fn(&mut DiagnosticBuilder<'_, ErrorGuaranteed>, bool, Span, &str, String) -> bool, + suggest: impl Fn(&mut Diagnostic, bool, Span, &str, String) -> bool, ) { let mut suggest_note = true; for rib in self.lifetime_ribs.iter().rev() { @@ -2149,7 +2149,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { pub(crate) fn add_missing_lifetime_specifiers_label( &mut self, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + err: &mut Diagnostic, lifetime_refs: Vec, function_param_lifetimes: Option<(Vec, Vec)>, ) { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 8a5c7fee697d1..758f1ef97664f 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -16,7 +16,8 @@ use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ - struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan, + struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError, + MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; @@ -2106,7 +2107,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn prohibit_generics<'a>( &self, segments: impl Iterator> + Clone, - extend: impl Fn(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>), + extend: impl Fn(&mut Diagnostic), ) -> bool { let args = segments.clone().flat_map(|segment| segment.args().args); @@ -2984,11 +2985,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } /// Make sure that we are in the condition to suggest the blanket implementation. - fn maybe_lint_blanket_trait_impl( - &self, - self_ty: &hir::Ty<'_>, - diag: &mut DiagnosticBuilder<'_, T>, - ) { + fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) { let tcx = self.tcx(); let parent_id = tcx.hir().get_parent_item(self_ty.hir_id); if let hir::Node::Item(hir::Item { @@ -3081,7 +3078,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { sugg, Applicability::MachineApplicable, ); - self.maybe_lint_blanket_trait_impl::<()>(&self_ty, &mut diag); + self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); diag.emit(); }, ); diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 6e3ef15f88433..5cdb2acd9f3c5 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1525,9 +1525,7 @@ fn detect_discriminant_duplicate<'tcx>( ) { // Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate. // Here `idx` refers to the order of which the discriminant appears, and its index in `vs` - let report = |dis: Discr<'tcx>, - idx: usize, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>| { + let report = |dis: Discr<'tcx>, idx: usize, err: &mut Diagnostic| { let var = &vs[idx]; // HIR for the duplicate discriminant let (span, display_discr) = match var.disr_expr { Some(ref expr) => { diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 540a8c3a83d95..04260d2122299 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1581,9 +1581,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } } - fn note_unreachable_loop_return<'a>( + fn note_unreachable_loop_return( &self, - err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>, + err: &mut Diagnostic, expr: &hir::Expr<'tcx>, ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>, ) { diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index fb78632069e44..d673c7dbd62a7 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -28,7 +28,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, - EmissionGuarantee, ErrorGuaranteed, + ErrorGuaranteed, }; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -879,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs: &'tcx hir::Expr<'tcx>, err_code: &'static str, op_span: Span, - adjust_err: impl FnOnce(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>), + adjust_err: impl FnOnce(&mut Diagnostic), ) { if lhs.is_syntactic_place_expr() { return; @@ -1089,8 +1089,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); - let suggest_deref_binop = |err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, - rhs_ty: Ty<'tcx>| { + let suggest_deref_binop = |err: &mut Diagnostic, rhs_ty: Ty<'tcx>| { if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { // Can only assign if the type is sized, so if `DerefMut` yields a type that is // unsized, do not suggest dereferencing it. @@ -2205,9 +2204,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx().ty_error() } - fn check_call_constructor( + fn check_call_constructor( &self, - err: &mut DiagnosticBuilder<'_, G>, + err: &mut Diagnostic, base: &'tcx hir::Expr<'tcx>, def_id: DefId, ) { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 660e7e4e39931..1d1f755947fdc 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1778,7 +1778,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn label_fn_like( &self, - err: &mut rustc_errors::DiagnosticBuilder<'tcx, rustc_errors::ErrorGuaranteed>, + err: &mut Diagnostic, callable_def_id: Option, callee_ty: Option>, ) { diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index c92b93cbc22d2..042ee768d5f2e 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -904,7 +904,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let label_span_not_found = |err: &mut DiagnosticBuilder<'_, _>| { + let label_span_not_found = |err: &mut Diagnostic| { if unsatisfied_predicates.is_empty() { err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); let is_string_or_ref_str = match actual.kind() { @@ -1150,7 +1150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, expr: &hir::Expr<'_>, item_name: Ident, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut Diagnostic, ) -> bool { let tcx = self.tcx; let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() { @@ -1327,7 +1327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_for_field_method( &self, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut Diagnostic, source: SelfSource<'tcx>, span: Span, actual: Ty<'tcx>, @@ -1375,7 +1375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_for_unwrap_self( &self, - err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + err: &mut Diagnostic, source: SelfSource<'tcx>, span: Span, actual: Ty<'tcx>, diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index b73d9a9eb7599..1b50209ee64cc 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -104,7 +104,7 @@ use crate::astconv::AstConv; use crate::check::gather_locals::GatherLocalsVisitor; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ - pluralize, struct_span_err, Applicability, DiagnosticBuilder, EmissionGuarantee, MultiSpan, + pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::Res; @@ -973,12 +973,7 @@ fn has_expected_num_generic_args<'tcx>( /// * `span` - The span of the snippet /// * `params` - The number of parameters the constructor accepts /// * `err` - A mutable diagnostic builder to add the suggestion to -fn suggest_call_constructor( - span: Span, - kind: CtorOf, - params: usize, - err: &mut DiagnosticBuilder<'_, G>, -) { +fn suggest_call_constructor(span: Span, kind: CtorOf, params: usize, err: &mut Diagnostic) { // Note: tuple-structs don't have named fields, so just use placeholders let args = vec!["_"; params].join(", "); let applicable = if params > 0 { diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 920b3e688089b..eb0c51bb2f979 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -59,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // Suppress this error, since we already emitted // a deref suggestion in check_overloaded_binop - err.delay_as_bug(); + err.downgrade_to_delayed_bug(); } } }); From a4f52a562240f32a757268c63589b1e4c3a0f934 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 10 Aug 2022 14:40:18 +0200 Subject: [PATCH 08/21] remove Clean trait implementation for ty::AssocItem --- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 11 +- src/librustdoc/clean/mod.rs | 334 ++++++++++++++------------- 3 files changed, 175 insertions(+), 172 deletions(-) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 01dd95e6e4093..da15c3c2b1fab 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -120,7 +120,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { items: cx.tcx .associated_items(impl_def_id) .in_definition_order() - .map(|x| x.clean(cx)) + .map(|x| clean_middle_assoc_item(x, cx)) .collect::>(), polarity: ty::ImplPolarity::Positive, kind: ImplKind::Blanket(Box::new(clean_middle_ty(trait_ref.0.self_ty(), cx, None))), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 4e9456ba7cb71..e56a715e85780 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -16,9 +16,10 @@ use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ - self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_field, - clean_middle_ty, clean_trait_ref_with_bindings, clean_ty, clean_ty_generics, clean_variant_def, - clean_visibility, utils, Attributes, AttributesExt, Clean, ImplKind, ItemId, Type, Visibility, + self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item, + clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty, + clean_ty_generics, clean_variant_def, clean_visibility, utils, Attributes, AttributesExt, + ImplKind, ItemId, Type, Visibility, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -217,7 +218,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean // which causes methods to have a `pub` prefix, which is invalid since items in traits // can not have a visibility prefix. Thus we override the visibility here manually. // See https://github.com/rust-lang/rust/issues/81274 - clean::Item { visibility: Visibility::Inherited, ..item.clean(cx) } + clean::Item { visibility: Visibility::Inherited, ..clean_middle_assoc_item(item, cx) } }) .collect(); @@ -452,7 +453,7 @@ pub(crate) fn build_impl( item.visibility(tcx).is_public() } }) - .map(|item| item.clean(cx)) + .map(|item| clean_middle_assoc_item(item, cx)) .collect::>(), clean::enter_impl_trait(cx, |cx| { clean_ty_generics(cx, tcx.generics_of(did), predicates) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 402e4f29860a2..8c983e3e23055 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1092,199 +1092,201 @@ pub(crate) fn clean_impl_item<'tcx>( }) } -impl<'tcx> Clean<'tcx, Item> for ty::AssocItem { - fn clean(&self, cx: &mut DocContext<'tcx>) -> Item { - let tcx = cx.tcx; - let kind = match self.kind { - ty::AssocKind::Const => { - let ty = clean_middle_ty(tcx.type_of(self.def_id), cx, Some(self.def_id)); - - let provided = match self.container { - ty::ImplContainer => true, - ty::TraitContainer => tcx.impl_defaultness(self.def_id).has_value(), - }; - if provided { - AssocConstItem(ty, ConstantKind::Extern { def_id: self.def_id }) - } else { - TyAssocConstItem(ty) - } +pub(crate) fn clean_middle_assoc_item<'tcx>( + assoc_item: &ty::AssocItem, + cx: &mut DocContext<'tcx>, +) -> Item { + let tcx = cx.tcx; + let kind = match assoc_item.kind { + ty::AssocKind::Const => { + let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id)); + + let provided = match assoc_item.container { + ty::ImplContainer => true, + ty::TraitContainer => tcx.impl_defaultness(assoc_item.def_id).has_value(), + }; + if provided { + AssocConstItem(ty, ConstantKind::Extern { def_id: assoc_item.def_id }) + } else { + TyAssocConstItem(ty) } - ty::AssocKind::Fn => { - let generics = clean_ty_generics( - cx, - tcx.generics_of(self.def_id), - tcx.explicit_predicates_of(self.def_id), - ); - let sig = tcx.fn_sig(self.def_id); - let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(self.def_id), sig); - - if self.fn_has_self_parameter { - let self_ty = match self.container { - ty::ImplContainer => tcx.type_of(self.container_id(tcx)), - ty::TraitContainer => tcx.types.self_param, - }; - let self_arg_ty = sig.input(0).skip_binder(); - if self_arg_ty == self_ty { - decl.inputs.values[0].type_ = Generic(kw::SelfUpper); - } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() { - if ty == self_ty { - match decl.inputs.values[0].type_ { - BorrowedRef { ref mut type_, .. } => { - **type_ = Generic(kw::SelfUpper) - } - _ => unreachable!(), - } + } + ty::AssocKind::Fn => { + let generics = clean_ty_generics( + cx, + tcx.generics_of(assoc_item.def_id), + tcx.explicit_predicates_of(assoc_item.def_id), + ); + let sig = tcx.fn_sig(assoc_item.def_id); + let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig); + + if assoc_item.fn_has_self_parameter { + let self_ty = match assoc_item.container { + ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)), + ty::TraitContainer => tcx.types.self_param, + }; + let self_arg_ty = sig.input(0).skip_binder(); + if self_arg_ty == self_ty { + decl.inputs.values[0].type_ = Generic(kw::SelfUpper); + } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() { + if ty == self_ty { + match decl.inputs.values[0].type_ { + BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper), + _ => unreachable!(), } } } + } - let provided = match self.container { - ty::ImplContainer => true, - ty::TraitContainer => self.defaultness(tcx).has_value(), + let provided = match assoc_item.container { + ty::ImplContainer => true, + ty::TraitContainer => assoc_item.defaultness(tcx).has_value(), + }; + if provided { + let defaultness = match assoc_item.container { + ty::ImplContainer => Some(assoc_item.defaultness(tcx)), + ty::TraitContainer => None, }; - if provided { - let defaultness = match self.container { - ty::ImplContainer => Some(self.defaultness(tcx)), - ty::TraitContainer => None, - }; - MethodItem(Box::new(Function { generics, decl }), defaultness) - } else { - TyMethodItem(Box::new(Function { generics, decl })) - } + MethodItem(Box::new(Function { generics, decl }), defaultness) + } else { + TyMethodItem(Box::new(Function { generics, decl })) } - ty::AssocKind::Type => { - let my_name = self.name; - - fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool { - match (¶m.kind, arg) { - (GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty))) - if *ty == param.name => - { - true - } - ( - GenericParamDefKind::Lifetime { .. }, - GenericArg::Lifetime(Lifetime(lt)), - ) if *lt == param.name => true, - (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => { - match &c.kind { - ConstantKind::TyConst { expr } => expr == param.name.as_str(), - _ => false, - } - } - _ => false, + } + ty::AssocKind::Type => { + let my_name = assoc_item.name; + + fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool { + match (¶m.kind, arg) { + (GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty))) + if *ty == param.name => + { + true } + (GenericParamDefKind::Lifetime { .. }, GenericArg::Lifetime(Lifetime(lt))) + if *lt == param.name => + { + true + } + (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &c.kind { + ConstantKind::TyConst { expr } => expr == param.name.as_str(), + _ => false, + }, + _ => false, } + } - if let ty::TraitContainer = self.container { - let bounds = tcx.explicit_item_bounds(self.def_id); - let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; - let mut generics = - clean_ty_generics(cx, tcx.generics_of(self.def_id), predicates); - // Filter out the bounds that are (likely?) directly attached to the associated type, - // as opposed to being located in the where clause. - let mut bounds = generics - .where_predicates - .drain_filter(|pred| match *pred { - WherePredicate::BoundPredicate { - ty: QPath { ref assoc, ref self_type, ref trait_, .. }, - .. - } => { - if assoc.name != my_name { - return false; - } - if trait_.def_id() != self.container_id(tcx) { - return false; - } - match **self_type { - Generic(ref s) if *s == kw::SelfUpper => {} - _ => return false, - } - match &assoc.args { - GenericArgs::AngleBracketed { args, bindings } => { - if !bindings.is_empty() - || generics - .params - .iter() - .zip(args.iter()) - .any(|(param, arg)| !param_eq_arg(param, arg)) - { - return false; - } - } - GenericArgs::Parenthesized { .. } => { - // The only time this happens is if we're inside the rustdoc for Fn(), - // which only has one associated type, which is not a GAT, so whatever. + if let ty::TraitContainer = assoc_item.container { + let bounds = tcx.explicit_item_bounds(assoc_item.def_id); + let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; + let mut generics = + clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), predicates); + // Filter out the bounds that are (likely?) directly attached to the associated type, + // as opposed to being located in the where clause. + let mut bounds = generics + .where_predicates + .drain_filter(|pred| match *pred { + WherePredicate::BoundPredicate { + ty: QPath { ref assoc, ref self_type, ref trait_, .. }, + .. + } => { + if assoc.name != my_name { + return false; + } + if trait_.def_id() != assoc_item.container_id(tcx) { + return false; + } + match **self_type { + Generic(ref s) if *s == kw::SelfUpper => {} + _ => return false, + } + match &assoc.args { + GenericArgs::AngleBracketed { args, bindings } => { + if !bindings.is_empty() + || generics + .params + .iter() + .zip(args.iter()) + .any(|(param, arg)| !param_eq_arg(param, arg)) + { + return false; } } - true - } - _ => false, - }) - .flat_map(|pred| { - if let WherePredicate::BoundPredicate { bounds, .. } = pred { - bounds - } else { - unreachable!() + GenericArgs::Parenthesized { .. } => { + // The only time this happens is if we're inside the rustdoc for Fn(), + // which only has one associated type, which is not a GAT, so whatever. + } } - }) - .collect::>(); - // Our Sized/?Sized bound didn't get handled when creating the generics - // because we didn't actually get our whole set of bounds until just now - // (some of them may have come from the trait). If we do have a sized - // bound, we remove it, and if we don't then we add the `?Sized` bound - // at the end. - match bounds.iter().position(|b| b.is_sized_bound(cx)) { - Some(i) => { - bounds.remove(i); + true } - None => bounds.push(GenericBound::maybe_sized(cx)), + _ => false, + }) + .flat_map(|pred| { + if let WherePredicate::BoundPredicate { bounds, .. } = pred { + bounds + } else { + unreachable!() + } + }) + .collect::>(); + // Our Sized/?Sized bound didn't get handled when creating the generics + // because we didn't actually get our whole set of bounds until just now + // (some of them may have come from the trait). If we do have a sized + // bound, we remove it, and if we don't then we add the `?Sized` bound + // at the end. + match bounds.iter().position(|b| b.is_sized_bound(cx)) { + Some(i) => { + bounds.remove(i); } + None => bounds.push(GenericBound::maybe_sized(cx)), + } - if tcx.impl_defaultness(self.def_id).has_value() { - AssocTypeItem( - Box::new(Typedef { - type_: clean_middle_ty( - tcx.type_of(self.def_id), - cx, - Some(self.def_id), - ), - generics, - // FIXME: should we obtain the Type from HIR and pass it on here? - item_type: None, - }), - bounds, - ) - } else { - TyAssocTypeItem(Box::new(generics), bounds) - } - } else { - // FIXME: when could this happen? Associated items in inherent impls? + if tcx.impl_defaultness(assoc_item.def_id).has_value() { AssocTypeItem( Box::new(Typedef { - type_: clean_middle_ty(tcx.type_of(self.def_id), cx, Some(self.def_id)), - generics: Generics { params: Vec::new(), where_predicates: Vec::new() }, + type_: clean_middle_ty( + tcx.type_of(assoc_item.def_id), + cx, + Some(assoc_item.def_id), + ), + generics, + // FIXME: should we obtain the Type from HIR and pass it on here? item_type: None, }), - Vec::new(), + bounds, ) + } else { + TyAssocTypeItem(Box::new(generics), bounds) } + } else { + // FIXME: when could this happen? Associated items in inherent impls? + AssocTypeItem( + Box::new(Typedef { + type_: clean_middle_ty( + tcx.type_of(assoc_item.def_id), + cx, + Some(assoc_item.def_id), + ), + generics: Generics { params: Vec::new(), where_predicates: Vec::new() }, + item_type: None, + }), + Vec::new(), + ) } - }; - - let mut what_rustc_thinks = - Item::from_def_id_and_parts(self.def_id, Some(self.name), kind, cx); + } + }; - let impl_ref = tcx.impl_trait_ref(tcx.parent(self.def_id)); + let mut what_rustc_thinks = + Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx); - // Trait impl items always inherit the impl's visibility -- - // we don't want to show `pub`. - if impl_ref.is_some() { - what_rustc_thinks.visibility = Visibility::Inherited; - } + let impl_ref = tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)); - what_rustc_thinks + // Trait impl items always inherit the impl's visibility -- + // we don't want to show `pub`. + if impl_ref.is_some() { + what_rustc_thinks.visibility = Visibility::Inherited; } + + what_rustc_thinks } fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type { From 0cd06fb4813bdd0e49528b380b3f19c37527616a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 10 Aug 2022 14:46:18 +0200 Subject: [PATCH 09/21] remove Clean trait implementation for hir::GenericArgs --- src/librustdoc/clean/mod.rs | 68 +++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8c983e3e23055..6e24638548979 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -123,7 +123,7 @@ fn clean_generic_bound<'tcx>( let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder(); - let generic_args = generic_args.clean(cx); + let generic_args = clean_generic_args(generic_args, cx); let GenericArgs::AngleBracketed { bindings, .. } = generic_args else { bug!("clean: parenthesized `GenericBound::LangItemTrait`"); @@ -1826,39 +1826,44 @@ fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path { Path { res: path.res, segments: path.segments.iter().map(|x| x.clean(cx)).collect() } } -impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> { - fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericArgs { - if self.parenthesized { - let output = clean_ty(self.bindings[0].ty(), cx); - let output = - if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None }; - let inputs = self.inputs().iter().map(|x| clean_ty(x, cx)).collect::>().into(); - GenericArgs::Parenthesized { inputs, output } - } else { - let args = self - .args - .iter() - .map(|arg| match arg { - hir::GenericArg::Lifetime(lt) if !lt.is_elided() => { - GenericArg::Lifetime(clean_lifetime(*lt, cx)) - } - hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), - hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), - hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), - hir::GenericArg::Infer(_inf) => GenericArg::Infer, - }) - .collect::>() - .into(); - let bindings = - self.bindings.iter().map(|x| clean_type_binding(x, cx)).collect::>().into(); - GenericArgs::AngleBracketed { args, bindings } - } +fn clean_generic_args<'tcx>( + generic_args: &hir::GenericArgs<'tcx>, + cx: &mut DocContext<'tcx>, +) -> GenericArgs { + if generic_args.parenthesized { + let output = clean_ty(generic_args.bindings[0].ty(), cx); + let output = if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None }; + let inputs = + generic_args.inputs().iter().map(|x| clean_ty(x, cx)).collect::>().into(); + GenericArgs::Parenthesized { inputs, output } + } else { + let args = generic_args + .args + .iter() + .map(|arg| match arg { + hir::GenericArg::Lifetime(lt) if !lt.is_elided() => { + GenericArg::Lifetime(clean_lifetime(*lt, cx)) + } + hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), + hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), + hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), + hir::GenericArg::Infer(_inf) => GenericArg::Infer, + }) + .collect::>() + .into(); + let bindings = generic_args + .bindings + .iter() + .map(|x| clean_type_binding(x, cx)) + .collect::>() + .into(); + GenericArgs::AngleBracketed { args, bindings } } } impl<'tcx> Clean<'tcx, PathSegment> for hir::PathSegment<'tcx> { fn clean(&self, cx: &mut DocContext<'tcx>) -> PathSegment { - PathSegment { name: self.ident.name, args: self.args().clean(cx) } + PathSegment { name: self.ident.name, args: clean_generic_args(self.args(), cx) } } } @@ -2228,7 +2233,10 @@ fn clean_type_binding<'tcx>( cx: &mut DocContext<'tcx>, ) -> TypeBinding { TypeBinding { - assoc: PathSegment { name: type_binding.ident.name, args: type_binding.gen_args.clean(cx) }, + assoc: PathSegment { + name: type_binding.ident.name, + args: clean_generic_args(type_binding.gen_args, cx), + }, kind: match type_binding.kind { hir::TypeBindingKind::Equality { ref term } => { TypeBindingKind::Equality { term: clean_hir_term(term, cx) } From 2a3ce7890c2e2c0b8e249aacfef44302f2b4d92a Mon Sep 17 00:00:00 2001 From: Martin Habovstiak Date: Wed, 10 Aug 2022 17:22:58 +0200 Subject: [PATCH 10/21] Stabilize ptr_const_cast This stabilizes `ptr_const_cast` feature as was decided in a recent [FCP](https://github.com/rust-lang/rust/issues/92675#issuecomment-1190660233) Closes #92675 --- compiler/rustc_arena/src/lib.rs | 1 - library/core/src/ptr/const_ptr.rs | 4 ++-- library/core/src/ptr/mut_ptr.rs | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index a5f1cbc96daa7..6529f11100d2d 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -19,7 +19,6 @@ #![feature(rustc_attrs)] #![cfg_attr(test, feature(test))] #![feature(strict_provenance)] -#![feature(ptr_const_cast)] use smallvec::SmallVec; diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index e0655d68d2cfa..833b57005ab4f 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -95,8 +95,8 @@ impl *const T { /// /// This is a bit safer than `as` because it wouldn't silently change the type if the code is /// refactored. - #[unstable(feature = "ptr_const_cast", issue = "92675")] - #[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")] + #[stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] pub const fn cast_mut(self) -> *mut T { self as _ } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index fc3dd2a9b25a9..5576fa60fbf7e 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -100,8 +100,8 @@ impl *mut T { /// coercion. /// /// [`cast_mut`]: #method.cast_mut - #[unstable(feature = "ptr_const_cast", issue = "92675")] - #[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")] + #[stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] pub const fn cast_const(self) -> *const T { self as _ } From 970184528718d7c10579cac7b7e7e66ef2e2a3f5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Aug 2022 15:21:11 +0200 Subject: [PATCH 11/21] Do not consider method call receiver as an argument in AST. --- compiler/rustc_ast/src/ast.rs | 11 +++--- compiler/rustc_ast/src/mut_visit.rs | 3 +- compiler/rustc_ast/src/util/parser.rs | 4 +-- compiler/rustc_ast/src/visit.rs | 3 +- compiler/rustc_ast_lowering/src/expr.rs | 6 ++-- .../rustc_ast_pretty/src/pprust/state/expr.rs | 14 +++++--- .../src/assert/context.rs | 21 ++++++------ compiler/rustc_lint/src/unused.rs | 3 +- compiler/rustc_parse/src/parser/expr.rs | 12 ++++--- compiler/rustc_resolve/src/late.rs | 5 ++- src/test/ui/cfg/cfg-method-receiver.rs | 12 +++++++ src/test/ui/cfg/cfg-method-receiver.stderr | 34 +++++++++++++++++++ .../clippy/clippy_lints/src/double_parens.rs | 5 ++- .../clippy_lints/src/option_env_unwrap.rs | 4 +-- .../clippy/clippy_lints/src/precedence.rs | 4 +-- .../src/suspicious_operation_groupings.rs | 2 +- .../clippy_lints/src/unused_rounding.rs | 5 ++- .../clippy/clippy_utils/src/ast_utils.rs | 4 ++- src/tools/rustfmt/src/chains.rs | 10 +++--- 19 files changed, 107 insertions(+), 55 deletions(-) create mode 100644 src/test/ui/cfg/cfg-method-receiver.rs create mode 100644 src/test/ui/cfg/cfg-method-receiver.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 870a7c0be33dc..22e325cc994fd 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1338,14 +1338,13 @@ pub enum ExprKind { /// /// The `PathSegment` represents the method name and its generic arguments /// (within the angle brackets). - /// The first element of the vector of an `Expr` is the expression that evaluates - /// to the object on which the method is being called on (the receiver), - /// and the remaining elements are the rest of the arguments. - /// Thus, `x.foo::(a, b, c, d)` is represented as - /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. + /// The standalone `Expr` is the receiver expression. + /// The vector of `Expr` is the arguments. + /// `x.foo::(a, b, c, d)` is represented as + /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d])`. /// This `Span` is the span of the function, without the dot and receiver /// (e.g. `foo(a, b)` in `x.foo(a, b)` - MethodCall(PathSegment, Vec>, Span), + MethodCall(PathSegment, P, Vec>, Span), /// A tuple (e.g., `(a, b, c, d)`). Tup(Vec>), /// A binary operation (e.g., `a + b`, `a * b`). diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 01bd498b37780..230c73c88e909 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1302,10 +1302,11 @@ pub fn noop_visit_expr( vis.visit_expr(f); visit_exprs(args, vis); } - ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => { + ExprKind::MethodCall(PathSegment { ident, id, args }, receiver, exprs, span) => { vis.visit_ident(ident); vis.visit_id(id); visit_opt(args, |args| vis.visit_generic_args(args)); + vis.visit_expr(receiver); visit_exprs(exprs, vis); vis.visit_span(span); } diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 74b7fe9e24955..5edeb54be5f0f 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -396,9 +396,9 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { contains_exterior_struct_lit(&x) } - ast::ExprKind::MethodCall(.., ref exprs, _) => { + ast::ExprKind::MethodCall(_, ref receiver, _, _) => { // X { y: 1 }.bar(...) - contains_exterior_struct_lit(&exprs[0]) + contains_exterior_struct_lit(&receiver) } _ => false, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index d9594b323dd0d..bedbb02f033c7 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -813,8 +813,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(callee_expression); walk_list!(visitor, visit_expr, arguments); } - ExprKind::MethodCall(ref segment, ref arguments, _span) => { + ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _span) => { visitor.visit_path_segment(expression.span, segment); + visitor.visit_expr(receiver); walk_list!(visitor, visit_expr, arguments); } ExprKind::Binary(_, ref left_expression, ref right_expression) => { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index fb6715ff17ee9..c7d35fdb1fd56 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -62,7 +62,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Call(f, self.lower_exprs(args)) } } - ExprKind::MethodCall(ref seg, ref args, span) => { + ExprKind::MethodCall(ref seg, ref receiver, ref args, span) => { let hir_seg = self.arena.alloc(self.lower_path_segment( e.span, seg, @@ -70,7 +70,9 @@ impl<'hir> LoweringContext<'_, 'hir> { ParenthesizedGenericArgs::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), )); - let args = self.lower_exprs(args); + let args = self.arena.alloc_from_iter( + [&*receiver].into_iter().chain(args.iter()).map(|x| self.lower_expr_mut(x)), + ); hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span)) } ExprKind::Binary(binop, ref lhs, ref rhs) => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index ead38caee287f..bcefa8ce0b9ce 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -193,9 +193,13 @@ impl<'a> State<'a> { self.print_call_post(args) } - fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P]) { - let base_args = &args[1..]; - self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); + fn print_expr_method_call( + &mut self, + segment: &ast::PathSegment, + receiver: &ast::Expr, + base_args: &[P], + ) { + self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX); self.word("."); self.print_ident(segment.ident); if let Some(ref args) = segment.args { @@ -303,8 +307,8 @@ impl<'a> State<'a> { ast::ExprKind::Call(ref func, ref args) => { self.print_expr_call(func, &args); } - ast::ExprKind::MethodCall(ref segment, ref args, _) => { - self.print_expr_method_call(segment, &args); + ast::ExprKind::MethodCall(ref segment, ref receiver, ref args, _) => { + self.print_expr_method_call(segment, &receiver, &args); } ast::ExprKind::Binary(op, ref lhs, ref rhs) => { self.print_expr_binary(op, lhs, rhs); diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index dcea883a5a378..c04d04020cc67 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -240,8 +240,8 @@ impl<'cx, 'a> Context<'cx, 'a> { self.manage_cond_expr(prefix); self.manage_cond_expr(suffix); } - ExprKind::MethodCall(_, ref mut local_exprs, _) => { - for local_expr in local_exprs.iter_mut().skip(1) { + ExprKind::MethodCall(_, _,ref mut local_exprs, _) => { + for local_expr in local_exprs.iter_mut() { self.manage_cond_expr(local_expr); } } @@ -377,14 +377,12 @@ impl<'cx, 'a> Context<'cx, 'a> { id: DUMMY_NODE_ID, ident: Ident::new(sym::try_capture, self.span), }, - vec![ - expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)), - expr_addr_of_mut( - self.cx, - self.span, - self.cx.expr_path(Path::from_ident(capture)), - ), - ], + expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)), + vec![expr_addr_of_mut( + self.cx, + self.span, + self.cx.expr_path(Path::from_ident(capture)), + )], self.span, )) .add_trailing_semicolon(); @@ -442,10 +440,11 @@ fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P) -> P { fn expr_method_call( cx: &ExtCtxt<'_>, path: PathSegment, + receiver: P, args: Vec>, span: Span, ) -> P { - cx.expr(span, ExprKind::MethodCall(path, args, span)) + cx.expr(span, ExprKind::MethodCall(path, receiver, args, span)) } fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P) -> P { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 4e7ba1c6ce4fa..58b2f0a44161c 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -608,8 +608,7 @@ trait UnusedDelimLint { ref call_or_other => { let (args_to_check, ctx) = match *call_or_other { Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg), - // first "argument" is self (which sometimes needs delims) - MethodCall(_, ref args, _) => (&args[1..], UnusedDelimsCtx::MethodArg), + MethodCall(_, _, ref args, _) => (&args[..], UnusedDelimsCtx::MethodArg), // actual catch-all arm _ => { return; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b8bd960a5b3d6..54ad6843e75e9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -850,7 +850,7 @@ impl<'a> Parser<'a> { ExprKind::Index(_, _) => "indexing", ExprKind::Try(_) => "`?`", ExprKind::Field(_, _) => "a field access", - ExprKind::MethodCall(_, _, _) => "a method call", + ExprKind::MethodCall(_, _, _, _) => "a method call", ExprKind::Call(_, _) => "a function call", ExprKind::Await(_) => "`.await`", ExprKind::Err => return Ok(with_postfix), @@ -1280,12 +1280,14 @@ impl<'a> Parser<'a> { if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { // Method call `expr.f()` - let mut args = self.parse_paren_expr_seq()?; - args.insert(0, self_arg); - + let args = self.parse_paren_expr_seq()?; let fn_span = fn_span_lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span); - Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args, fn_span), AttrVec::new())) + Ok(self.mk_expr( + span, + ExprKind::MethodCall(segment, self_arg, args, fn_span), + AttrVec::new(), + )) } else { // Field access `expr.f` if let Some(args) = segment.args { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ac8d26fb0724a..cbd0ca49c99bc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3796,9 +3796,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ExprKind::Field(ref subexpression, _) => { self.resolve_expr(subexpression, Some(expr)); } - ExprKind::MethodCall(ref segment, ref arguments, _) => { - let mut arguments = arguments.iter(); - self.resolve_expr(arguments.next().unwrap(), Some(expr)); + ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _) => { + self.resolve_expr(receiver, Some(expr)); for argument in arguments { self.resolve_expr(argument, None); } diff --git a/src/test/ui/cfg/cfg-method-receiver.rs b/src/test/ui/cfg/cfg-method-receiver.rs new file mode 100644 index 0000000000000..78a072f503fab --- /dev/null +++ b/src/test/ui/cfg/cfg-method-receiver.rs @@ -0,0 +1,12 @@ +macro_rules! cbor_map { + ($key:expr) => { + $key.signum(); + //~^ ERROR can't call method `signum` on ambiguous numeric type `{integer}` [E0689] + }; +} + +fn main() { + cbor_map! { #[cfg(test)] 4}; + //~^ ERROR attributes on expressions are experimental + //~| ERROR removing an expression is not supported in this position +} diff --git a/src/test/ui/cfg/cfg-method-receiver.stderr b/src/test/ui/cfg/cfg-method-receiver.stderr new file mode 100644 index 0000000000000..517fc8168e72d --- /dev/null +++ b/src/test/ui/cfg/cfg-method-receiver.stderr @@ -0,0 +1,34 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/cfg-method-receiver.rs:9:17 + | +LL | cbor_map! { #[cfg(test)] 4}; + | ^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: removing an expression is not supported in this position + --> $DIR/cfg-method-receiver.rs:9:17 + | +LL | cbor_map! { #[cfg(test)] 4}; + | ^^^^^^^^^^^^ + +error[E0689]: can't call method `signum` on ambiguous numeric type `{integer}` + --> $DIR/cfg-method-receiver.rs:3:14 + | +LL | $key.signum(); + | ^^^^^^ +... +LL | cbor_map! { #[cfg(test)] 4}; + | --------------------------- in this macro invocation + | + = note: this error originates in the macro `cbor_map` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you must specify a concrete type for this numeric value, like `i32` + | +LL | cbor_map! { #[cfg(test)] 4_i32}; + | ~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0658, E0689. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs index a33ef5ce6e37c..0f1d701865e7d 100644 --- a/src/tools/clippy/clippy_lints/src/double_parens.rs +++ b/src/tools/clippy/clippy_lints/src/double_parens.rs @@ -61,9 +61,8 @@ impl EarlyLintPass for DoubleParens { } } }, - ExprKind::MethodCall(_, ref params, _) => { - if params.len() == 2 { - let param = ¶ms[1]; + ExprKind::MethodCall(_, _, ref params, _) => { + if let [ref param] = params[..] { if let ExprKind::Paren(_) = param.kind { span_lint(cx, DOUBLE_PARENS, param.span, msg); } diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs index 3f5286ba097b5..d9ee031c9f975 100644 --- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs @@ -37,9 +37,9 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]); impl EarlyLintPass for OptionEnvUnwrap { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if_chain! { - if let ExprKind::MethodCall(path_segment, args, _) = &expr.kind; + if let ExprKind::MethodCall(path_segment, receiver, _, _) = &expr.kind; if matches!(path_segment.ident.name, sym::expect | sym::unwrap); - if let ExprKind::Call(caller, _) = &args[0].kind; + if let ExprKind::Call(caller, _) = &receiver.kind; if is_direct_expn_of(caller.span, "option_env").is_some(); then { span_lint_and_help( diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs index cc0533c9f5d1a..e6e3ad05ad70a 100644 --- a/src/tools/clippy/clippy_lints/src/precedence.rs +++ b/src/tools/clippy/clippy_lints/src/precedence.rs @@ -109,12 +109,12 @@ impl EarlyLintPass for Precedence { let mut arg = operand; let mut all_odd = true; - while let ExprKind::MethodCall(path_segment, args, _) = &arg.kind { + while let ExprKind::MethodCall(path_segment, receiver, _, _) = &arg.kind { let path_segment_str = path_segment.ident.name.as_str(); all_odd &= ALLOWED_ODD_FUNCTIONS .iter() .any(|odd_function| **odd_function == *path_segment_str); - arg = args.first().expect("A method always has a receiver."); + arg = receiver; } if_chain! { diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index fe8859905953f..5d36f0f5ff8bc 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -595,7 +595,7 @@ fn ident_difference_expr_with_base_location( | (Unary(_, _), Unary(_, _)) | (Binary(_, _, _), Binary(_, _, _)) | (Tup(_), Tup(_)) - | (MethodCall(_, _, _), MethodCall(_, _, _)) + | (MethodCall(_, _, _, _), MethodCall(_, _, _, _)) | (Call(_, _), Call(_, _)) | (ConstBlock(_), ConstBlock(_)) | (Array(_), Array(_)) diff --git a/src/tools/clippy/clippy_lints/src/unused_rounding.rs b/src/tools/clippy/clippy_lints/src/unused_rounding.rs index 306afe4414847..e1ec357838dbd 100644 --- a/src/tools/clippy/clippy_lints/src/unused_rounding.rs +++ b/src/tools/clippy/clippy_lints/src/unused_rounding.rs @@ -30,11 +30,10 @@ declare_clippy_lint! { declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]); fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> { - if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind + if let ExprKind::MethodCall(name_ident, receiver, _, _) = &expr.kind && let method_name = name_ident.ident.name.as_str() && (method_name == "ceil" || method_name == "round" || method_name == "floor") - && !args.is_empty() - && let ExprKind::Lit(spanned) = &args[0].kind + && let ExprKind::Lit(spanned) = &receiver.kind && let LitKind::Float(symbol, ty) = spanned.kind { let f = symbol.as_str().parse::().unwrap(); let f_str = symbol.to_string() + if let LitFloatType::Suffixed(ty) = ty { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index b226026323be8..9f74729bdfa18 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -147,7 +147,9 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)), (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value), (Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)), - (MethodCall(lc, la, _), MethodCall(rc, ra, _)) => eq_path_seg(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)), + (MethodCall(lc, ls, la, _), MethodCall(rc, rs, ra, _)) => { + eq_path_seg(lc, rc) && eq_expr(ls, rs) && over(la, ra, |l, r| eq_expr(l, r)) + }, (Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr), (Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r), (Lit(l), Lit(r)) => l.kind == r.kind, diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs index e26e24ec55ad6..fcc02eca42987 100644 --- a/src/tools/rustfmt/src/chains.rs +++ b/src/tools/rustfmt/src/chains.rs @@ -145,7 +145,7 @@ impl ChainItemKind { fn from_ast(context: &RewriteContext<'_>, expr: &ast::Expr) -> (ChainItemKind, Span) { let (kind, span) = match expr.kind { - ast::ExprKind::MethodCall(ref segment, ref expressions, _) => { + ast::ExprKind::MethodCall(ref segment, ref receiver, ref expressions, _) => { let types = if let Some(ref generic_args) = segment.args { if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { data.args @@ -163,7 +163,7 @@ impl ChainItemKind { } else { vec![] }; - let span = mk_sp(expressions[0].span.hi(), expr.span.hi()); + let span = mk_sp(receiver.span.hi(), expr.span.hi()); let kind = ChainItemKind::MethodCall(segment.clone(), types, expressions.clone()); (kind, span) } @@ -253,7 +253,7 @@ impl ChainItem { format!("::<{}>", type_list.join(", ")) }; let callee_str = format!(".{}{}", rewrite_ident(context, method_name), type_str); - rewrite_call(context, &callee_str, &args[1..], span, shape) + rewrite_call(context, &callee_str, &args, span, shape) } } @@ -400,8 +400,8 @@ impl Chain { // is a try! macro, we'll convert it to shorthand when the option is set. fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option { match expr.kind { - ast::ExprKind::MethodCall(_, ref expressions, _) => { - Some(Self::convert_try(&expressions[0], context)) + ast::ExprKind::MethodCall(_, ref receiver, _, _) => { + Some(Self::convert_try(&receiver, context)) } ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) From 69205db766acb80181462f3293a502c5a32d2ca5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Aug 2022 17:36:00 +0200 Subject: [PATCH 12/21] Adapt ui-fulldeps test. --- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index a679b7b4e1913..0d9c9350efca4 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -74,10 +74,10 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P)) { 2 => { let seg = PathSegment::from_ident(Ident::from_str("x")); iter_exprs(depth - 1, &mut |e| { - g(ExprKind::MethodCall(seg.clone(), vec![e, make_x()], DUMMY_SP)) + g(ExprKind::MethodCall(seg.clone(), e, vec![make_x()], DUMMY_SP)) }); iter_exprs(depth - 1, &mut |e| { - g(ExprKind::MethodCall(seg.clone(), vec![make_x(), e], DUMMY_SP)) + g(ExprKind::MethodCall(seg.clone(), make_x(), vec![e], DUMMY_SP)) }); } 3..=8 => { From a3b84ad197fb209d903857df747af3ca0a1f2c25 Mon Sep 17 00:00:00 2001 From: Lamb Date: Mon, 10 Jan 2022 21:01:23 +0000 Subject: [PATCH 13/21] Check if extern crate enum has non exhaustive variant when cast --- compiler/rustc_typeck/src/check/cast.rs | 23 ++++++++++++++++++- .../rfc-2008-non-exhaustive/enum-as-cast.rs | 8 +------ .../enum-as-cast.stderr | 11 +++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 7aaddc2bd7aab..88bce06297bdb 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -32,6 +32,7 @@ use super::FnCtxt; use crate::hir::def_id::DefId; use crate::type_error_struct; +use hir::def_id::LOCAL_CRATE; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; @@ -40,7 +41,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::cast::{CastKind, CastTy}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable}; +use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef}; use rustc_session::lint; use rustc_session::Session; use rustc_span::symbol::sym; @@ -173,6 +174,7 @@ pub enum CastError { /// or "a length". If this argument is None, then the metadata is unknown, for example, /// when we're typechecking a type parameter with a ?Sized bound. IntToFatCast(Option<&'static str>), + ForeignNonExhaustiveAdt, } impl From for CastError { @@ -591,6 +593,17 @@ impl<'a, 'tcx> CastCheck<'tcx> { } err.emit(); } + CastError::ForeignNonExhaustiveAdt => { + make_invalid_casting_error( + fcx.tcx.sess, + self.span, + self.expr_ty, + self.cast_ty, + fcx, + ) + .note("cannot cast a non-exhaustive enum defined in another crate") + .emit(); + } } } @@ -789,6 +802,14 @@ impl<'a, 'tcx> CastCheck<'tcx> { _ => return Err(CastError::NonScalar), }; + if let ty::Adt(adt_def, _) = *self.expr_ty.kind() { + if adt_def.did().krate != LOCAL_CRATE { + if adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) { + return Err(CastError::ForeignNonExhaustiveAdt); + } + } + } + match (t_from, t_cast) { // These types have invariants! can't cast into them. (_, Int(CEnum) | FnPtr) => Err(CastError::NonScalar), diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs index d9657bac77685..5dce8180f5920 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs @@ -1,5 +1,4 @@ // aux-build:enums.rs -// run-pass extern crate enums; @@ -7,11 +6,6 @@ use enums::FieldLessWithNonExhaustiveVariant; fn main() { let e = FieldLessWithNonExhaustiveVariant::default(); - // FIXME: https://github.com/rust-lang/rust/issues/91161 - // This `as` cast *should* be an error, since it would fail - // if the non-exhaustive variant got fields. But today it - // doesn't. The fix for that will update this test to - // show an error (and not be run-pass any more). - let d = e as u8; + let d = e as u8; //~ ERROR casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid [E0606] assert_eq!(d, 0); } diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr new file mode 100644 index 0000000000000..c5f0105296fff --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr @@ -0,0 +1,11 @@ +error[E0606]: casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid + --> $DIR/enum-as-cast.rs:9:13 + | +LL | let d = e as u8; + | ^^^^^^^ + | + = note: cannot cast a non-exhaustive enum defined in another crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. From dfb3713cdb7303a250d8b23792fe801319edf36c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 10 Aug 2022 10:02:03 -0700 Subject: [PATCH 14/21] Update error message to clarify that it's not the enum itself that's non_exhaustive --- compiler/rustc_typeck/src/check/cast.rs | 2 +- src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 88bce06297bdb..6c7b2a2889fa4 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -601,7 +601,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.cast_ty, fcx, ) - .note("cannot cast a non-exhaustive enum defined in another crate") + .note("cannot cast an enum with a non-exhaustive variant when it's defined in another crate") .emit(); } } diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr index c5f0105296fff..a61dcf8399f17 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr @@ -4,7 +4,7 @@ error[E0606]: casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid LL | let d = e as u8; | ^^^^^^^ | - = note: cannot cast a non-exhaustive enum defined in another crate + = note: cannot cast an enum with a non-exhaustive variant when it's defined in another crate error: aborting due to previous error From bf20777d1310431178c50b7b8dad0537d5e4d4f7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 11 Aug 2022 10:11:13 +1000 Subject: [PATCH 15/21] Add a test for `-Zhir-stats` output. This will be very useful in subsequent commits where I will improve the output. --- src/test/ui/stats/hir-stats.rs | 41 +++++++++++++++ src/test/ui/stats/hir-stats.stderr | 83 ++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/test/ui/stats/hir-stats.rs create mode 100644 src/test/ui/stats/hir-stats.stderr diff --git a/src/test/ui/stats/hir-stats.rs b/src/test/ui/stats/hir-stats.rs new file mode 100644 index 0000000000000..3c59ee22f24c5 --- /dev/null +++ b/src/test/ui/stats/hir-stats.rs @@ -0,0 +1,41 @@ +// check-pass +// compile-flags: -Zhir-stats +// only-x86_64 + +// The aim here is to include at least one of every different type of AST/HIR +// node reported by `-Zhir-stats`. + +#![allow(dead_code)] + +use std::arch::asm; +use std::fmt::Debug; +use std::ffi::c_void; + +extern "C" { fn f(p: *mut c_void); } + +/// An enum. +enum E<'a, T: Copy> { A { t: T }, B(&'a u32) } + +trait Go { + type G: Debug; + fn go(self) -> u32; +} + +impl<'a, T: Copy> Go for E<'a, T> { + type G = bool; + fn go(self) -> u32 { + 99 + } +} + +fn f2(t: T) where T: Debug {} + +fn main() { + let x = E::A { t: 3 }; + match x { + E::A { .. } => {} + _ => {} + } + + unsafe { asm!("mov rdi, 1"); } +} diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr new file mode 100644 index 0000000000000..a0c1c80022f2b --- /dev/null +++ b/src/test/ui/stats/hir-stats.stderr @@ -0,0 +1,83 @@ + +PRE EXPANSION AST STATS + +Name Accumulated Size Count Item Size +---------------------------------------------------------------- +Lifetime 32 2 16 +MacCall 64 1 64 +Local 72 1 72 +Arm 96 2 48 +FieldDef 160 2 80 +ForeignItem 160 1 160 +Stmt 160 5 32 +FnDecl 200 5 40 +Variant 240 2 120 +Block 288 6 48 +Attribute 304 2 152 +ImplItem 320 2 160 +TraitItem 320 2 160 +GenericBound 352 4 88 +PathSegment 720 30 24 +Expr 832 8 104 +Pat 840 7 120 +Ty 1_344 14 96 +Item 1_800 9 200 +---------------------------------------------------------------- +Total 8_304 + + +POST EXPANSION AST STATS + +Name Accumulated Size Count Item Size +---------------------------------------------------------------- +Lifetime 32 2 16 +Local 72 1 72 +Arm 96 2 48 +FieldDef 160 2 80 +ForeignItem 160 1 160 +Stmt 160 5 32 +FnDecl 200 5 40 +Variant 240 2 120 +Block 288 6 48 +ImplItem 320 2 160 +TraitItem 320 2 160 +GenericBound 352 4 88 +Attribute 608 4 152 +PathSegment 792 33 24 +Pat 840 7 120 +Expr 936 9 104 +Ty 1_344 14 96 +Item 2_200 11 200 +---------------------------------------------------------------- +Total 9_120 + + +HIR STATS + +Name Accumulated Size Count Item Size +---------------------------------------------------------------- +Param 64 2 32 +Local 64 1 64 +ForeignItem 72 1 72 +FieldDef 96 2 48 +Arm 96 2 48 +Stmt 96 3 32 +FnDecl 120 3 40 +Lifetime 128 4 32 +Variant 160 2 80 +ImplItem 176 2 88 +GenericBound 192 4 48 +TraitItem 192 2 96 +WherePredicate 216 3 72 +Block 288 6 48 +QPath 408 17 24 +Pat 440 5 88 +Attribute 608 4 152 +Expr 672 12 56 +Item 960 12 80 +Ty 1_152 16 72 +Path 1_296 27 48 +PathSegment 2_240 40 56 +---------------------------------------------------------------- +Total 9_736 + From 288b6672be6560fe45f8bb033d581379ec38b4a0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 11 Aug 2022 12:18:21 +1000 Subject: [PATCH 16/21] Improve AST stat collector. This commit: - Adds a comment explaining which `visit_*` methods should be implemented. - Adds and removes some `visit_*` methods accordingly, improving coverage, and avoiding some double counting. --- compiler/rustc_passes/src/hir_stats.rs | 79 +++++++++++++++++++++----- src/test/ui/stats/hir-stats.stderr | 20 +++++-- 2 files changed, 81 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index a3be827a7ccec..080c7df47a0e9 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -26,6 +26,23 @@ struct NodeData { size: usize, } +/// This type measures the size of AST and HIR nodes, by implementing the AST +/// and HIR `Visitor` traits. But we don't measure every visited type because +/// that could cause double counting. +/// +/// For example, `ast::Visitor` has `visit_ident`, but `Ident`s are always +/// stored inline within other AST nodes, so we don't implement `visit_ident` +/// here. In constrast, we do implement `visit_expr` because `ast::Expr` is +/// always stored as `P`, and every such expression should be +/// measured separately. +/// +/// In general, a `visit_foo` method should be implemented here if the +/// corresponding `Foo` type is always stored on its own, e.g.: `P`, +/// `Box`, `Vec`, `Box<[Foo]>`. +/// +/// There are some types in the AST and HIR tree that the visitors do not have +/// a `visit_*` method for, and so we cannot measure these, which is +/// unfortunate. struct StatCollector<'k> { krate: Option>, data: FxHashMap<&'static str, NodeData>, @@ -44,9 +61,11 @@ pub fn print_hir_stats(tcx: TyCtxt<'_>) { } pub fn print_ast_stats(krate: &ast::Crate, title: &str) { + use rustc_ast::visit::Visitor; + let mut collector = StatCollector { krate: None, data: FxHashMap::default(), seen: FxHashSet::default() }; - ast_visit::walk_crate(&mut collector, krate); + collector.visit_crate(krate); collector.print(title); } @@ -228,6 +247,10 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_path(self, path) } + // `PathSegment` has one inline use (in `ast::ExprKind::MethodCall`) and + // one non-inline use (in `Path::segments`). The latter case is more common + // than the former case, so we implement this visitor and tolerate the + // double counting in the former case. fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v hir::PathSegment<'v>) { self.record("PathSegment", Id::None, path_segment); hir_visit::walk_path_segment(self, path_span, path_segment) @@ -269,6 +292,11 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_stmt(self, s) } + fn visit_param(&mut self, p: &'v ast::Param) { + self.record("Param", Id::None, p); + ast_visit::walk_param(self, p) + } + fn visit_arm(&mut self, a: &'v ast::Arm) { self.record("Arm", Id::None, a); ast_visit::walk_arm(self, a) @@ -289,6 +317,16 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_ty(self, t) } + fn visit_generic_param(&mut self, g: &'v ast::GenericParam) { + self.record("GenericParam", Id::None, g); + ast_visit::walk_generic_param(self, g) + } + + fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) { + self.record("WherePredicate", Id::None, p); + ast_visit::walk_where_predicate(self, p) + } + fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, s: Span, _: NodeId) { self.record("FnDecl", Id::None, fk.decl()); ast_visit::walk_fn(self, fk, s) @@ -318,27 +356,42 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_variant(self, v) } - fn visit_lifetime(&mut self, lifetime: &'v ast::Lifetime, _: ast_visit::LifetimeCtxt) { - self.record("Lifetime", Id::None, lifetime); - ast_visit::walk_lifetime(self, lifetime) - } - - fn visit_mac_call(&mut self, mac: &'v ast::MacCall) { - self.record("MacCall", Id::None, mac); - ast_visit::walk_mac(self, mac) - } + // `UseTree` has one inline use (in `ast::ItemKind::Use`) and one + // non-inline use (in `ast::UseTreeKind::Nested). The former case is more + // common, so we don't implement `visit_use_tree` and tolerate the missed + // coverage in the latter case. fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSegment) { self.record("PathSegment", Id::None, path_segment); ast_visit::walk_path_segment(self, path_span, path_segment) } - fn visit_assoc_constraint(&mut self, constraint: &'v ast::AssocConstraint) { - self.record("AssocConstraint", Id::None, constraint); - ast_visit::walk_assoc_constraint(self, constraint) + // `GenericArgs` has one inline use (in `ast::AssocConstraint::gen_args`) and one + // non-inline use (in `ast::PathSegment::args`). The latter case is more + // common, so we implement `visit_generic_args` and tolerate the double + // counting in the former case. + fn visit_generic_args(&mut self, sp: Span, g: &'v ast::GenericArgs) { + self.record("GenericArgs", Id::None, g); + ast_visit::walk_generic_args(self, sp, g) } fn visit_attribute(&mut self, attr: &'v ast::Attribute) { self.record("Attribute", Id::None, attr); + ast_visit::walk_attribute(self, attr) + } + + fn visit_expr_field(&mut self, f: &'v ast::ExprField) { + self.record("ExprField", Id::None, f); + ast_visit::walk_expr_field(self, f) + } + + fn visit_crate(&mut self, krate: &'v ast::Crate) { + self.record("Crate", Id::None, krate); + ast_visit::walk_crate(self, krate) + } + + fn visit_inline_asm(&mut self, asm: &'v ast::InlineAsm) { + self.record("InlineAsm", Id::None, asm); + ast_visit::walk_inline_asm(self, asm) } } diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index a0c1c80022f2b..8e2daebcf0ad0 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -3,13 +3,16 @@ PRE EXPANSION AST STATS Name Accumulated Size Count Item Size ---------------------------------------------------------------- -Lifetime 32 2 16 -MacCall 64 1 64 +ExprField 48 1 48 +GenericArgs 64 1 64 Local 72 1 72 +WherePredicate 72 1 72 +Crate 72 1 72 Arm 96 2 48 FieldDef 160 2 80 ForeignItem 160 1 160 Stmt 160 5 32 +Param 160 4 40 FnDecl 200 5 40 Variant 240 2 120 Block 288 6 48 @@ -17,31 +20,38 @@ Attribute 304 2 152 ImplItem 320 2 160 TraitItem 320 2 160 GenericBound 352 4 88 +GenericParam 520 5 104 PathSegment 720 30 24 Expr 832 8 104 Pat 840 7 120 Ty 1_344 14 96 Item 1_800 9 200 ---------------------------------------------------------------- -Total 8_304 +Total 9_144 POST EXPANSION AST STATS Name Accumulated Size Count Item Size ---------------------------------------------------------------- -Lifetime 32 2 16 +ExprField 48 1 48 +GenericArgs 64 1 64 Local 72 1 72 +WherePredicate 72 1 72 +Crate 72 1 72 Arm 96 2 48 +InlineAsm 120 1 120 FieldDef 160 2 80 ForeignItem 160 1 160 Stmt 160 5 32 +Param 160 4 40 FnDecl 200 5 40 Variant 240 2 120 Block 288 6 48 ImplItem 320 2 160 TraitItem 320 2 160 GenericBound 352 4 88 +GenericParam 520 5 104 Attribute 608 4 152 PathSegment 792 33 24 Pat 840 7 120 @@ -49,7 +59,7 @@ Expr 936 9 104 Ty 1_344 14 96 Item 2_200 11 200 ---------------------------------------------------------------- -Total 9_120 +Total 10_144 HIR STATS From 6a3c663cbb65b08c7a7356cc3745eb9b75493bc6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 11 Aug 2022 12:34:52 +1000 Subject: [PATCH 17/21] Change how `AssocItem` is reported. Currently it's reported as either `TraitItem` or `ImplItem`. This commit changes it to `AssocItem`, because having the report match the type name is (a) consistent with other types, and (b) the trait/impl split isn't that important here. --- compiler/rustc_passes/src/hir_stats.rs | 6 +----- src/test/ui/stats/hir-stats.stderr | 6 ++---- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 080c7df47a0e9..9d3663240921a 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -333,11 +333,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_assoc_item(&mut self, item: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) { - let label = match ctxt { - ast_visit::AssocCtxt::Trait => "TraitItem", - ast_visit::AssocCtxt::Impl => "ImplItem", - }; - self.record(label, Id::None, item); + self.record("AssocItem", Id::None, item); ast_visit::walk_assoc_item(self, item, ctxt); } diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 8e2daebcf0ad0..1b2eafc68db2b 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -17,10 +17,9 @@ FnDecl 200 5 40 Variant 240 2 120 Block 288 6 48 Attribute 304 2 152 -ImplItem 320 2 160 -TraitItem 320 2 160 GenericBound 352 4 88 GenericParam 520 5 104 +AssocItem 640 4 160 PathSegment 720 30 24 Expr 832 8 104 Pat 840 7 120 @@ -48,11 +47,10 @@ Param 160 4 40 FnDecl 200 5 40 Variant 240 2 120 Block 288 6 48 -ImplItem 320 2 160 -TraitItem 320 2 160 GenericBound 352 4 88 GenericParam 520 5 104 Attribute 608 4 152 +AssocItem 640 4 160 PathSegment 792 33 24 Pat 840 7 120 Expr 936 9 104 From 85c749266d1e9a38a9fd9c45ef417d0d464ef634 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 11 Aug 2022 13:46:26 +1000 Subject: [PATCH 18/21] Add percentages to `-Zhir-stats` output. --- compiler/rustc_passes/src/hir_stats.rs | 14 +-- src/test/ui/stats/hir-stats.stderr | 140 ++++++++++++------------- 2 files changed, 78 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 9d3663240921a..0c6c1d1aa2b8e 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -86,26 +86,28 @@ impl<'k> StatCollector<'k> { stats.sort_by_key(|&(_, ref d)| d.count * d.size); - let mut total_size = 0; + let total_size = stats.iter().map(|(_, data)| data.count * data.size).sum(); eprintln!("\n{}\n", title); eprintln!("{:<18}{:>18}{:>14}{:>14}", "Name", "Accumulated Size", "Count", "Item Size"); eprintln!("----------------------------------------------------------------"); + let percent = |m, n| { (m * 100) as f64 / n as f64 }; + for (label, data) in stats { + let size = data.count * data.size; eprintln!( - "{:<18}{:>18}{:>14}{:>14}", + "{:<18}{:>10} ({:4.1}%){:>14}{:>14}", label, - to_readable_str(data.count * data.size), + to_readable_str(size), + percent(size, total_size), to_readable_str(data.count), to_readable_str(data.size) ); - - total_size += data.count * data.size; } eprintln!("----------------------------------------------------------------"); - eprintln!("{:<18}{:>18}\n", "Total", to_readable_str(total_size)); + eprintln!("{:<18}{:>10}\n", "Total", to_readable_str(total_size)); } } diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 1b2eafc68db2b..132fff1972f4f 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -3,89 +3,89 @@ PRE EXPANSION AST STATS Name Accumulated Size Count Item Size ---------------------------------------------------------------- -ExprField 48 1 48 -GenericArgs 64 1 64 -Local 72 1 72 -WherePredicate 72 1 72 -Crate 72 1 72 -Arm 96 2 48 -FieldDef 160 2 80 -ForeignItem 160 1 160 -Stmt 160 5 32 -Param 160 4 40 -FnDecl 200 5 40 -Variant 240 2 120 -Block 288 6 48 -Attribute 304 2 152 -GenericBound 352 4 88 -GenericParam 520 5 104 -AssocItem 640 4 160 -PathSegment 720 30 24 -Expr 832 8 104 -Pat 840 7 120 -Ty 1_344 14 96 -Item 1_800 9 200 +ExprField 48 ( 0.5%) 1 48 +GenericArgs 64 ( 0.7%) 1 64 +Local 72 ( 0.8%) 1 72 +WherePredicate 72 ( 0.8%) 1 72 +Crate 72 ( 0.8%) 1 72 +Arm 96 ( 1.0%) 2 48 +FieldDef 160 ( 1.7%) 2 80 +ForeignItem 160 ( 1.7%) 1 160 +Stmt 160 ( 1.7%) 5 32 +Param 160 ( 1.7%) 4 40 +FnDecl 200 ( 2.2%) 5 40 +Variant 240 ( 2.6%) 2 120 +Block 288 ( 3.1%) 6 48 +Attribute 304 ( 3.3%) 2 152 +GenericBound 352 ( 3.8%) 4 88 +GenericParam 520 ( 5.7%) 5 104 +AssocItem 640 ( 7.0%) 4 160 +PathSegment 720 ( 7.9%) 30 24 +Expr 832 ( 9.1%) 8 104 +Pat 840 ( 9.2%) 7 120 +Ty 1_344 (14.7%) 14 96 +Item 1_800 (19.7%) 9 200 ---------------------------------------------------------------- -Total 9_144 +Total 9_144 POST EXPANSION AST STATS Name Accumulated Size Count Item Size ---------------------------------------------------------------- -ExprField 48 1 48 -GenericArgs 64 1 64 -Local 72 1 72 -WherePredicate 72 1 72 -Crate 72 1 72 -Arm 96 2 48 -InlineAsm 120 1 120 -FieldDef 160 2 80 -ForeignItem 160 1 160 -Stmt 160 5 32 -Param 160 4 40 -FnDecl 200 5 40 -Variant 240 2 120 -Block 288 6 48 -GenericBound 352 4 88 -GenericParam 520 5 104 -Attribute 608 4 152 -AssocItem 640 4 160 -PathSegment 792 33 24 -Pat 840 7 120 -Expr 936 9 104 -Ty 1_344 14 96 -Item 2_200 11 200 +ExprField 48 ( 0.5%) 1 48 +GenericArgs 64 ( 0.6%) 1 64 +Local 72 ( 0.7%) 1 72 +WherePredicate 72 ( 0.7%) 1 72 +Crate 72 ( 0.7%) 1 72 +Arm 96 ( 0.9%) 2 48 +InlineAsm 120 ( 1.2%) 1 120 +FieldDef 160 ( 1.6%) 2 80 +ForeignItem 160 ( 1.6%) 1 160 +Stmt 160 ( 1.6%) 5 32 +Param 160 ( 1.6%) 4 40 +FnDecl 200 ( 2.0%) 5 40 +Variant 240 ( 2.4%) 2 120 +Block 288 ( 2.8%) 6 48 +GenericBound 352 ( 3.5%) 4 88 +GenericParam 520 ( 5.1%) 5 104 +Attribute 608 ( 6.0%) 4 152 +AssocItem 640 ( 6.3%) 4 160 +PathSegment 792 ( 7.8%) 33 24 +Pat 840 ( 8.3%) 7 120 +Expr 936 ( 9.2%) 9 104 +Ty 1_344 (13.2%) 14 96 +Item 2_200 (21.7%) 11 200 ---------------------------------------------------------------- -Total 10_144 +Total 10_144 HIR STATS Name Accumulated Size Count Item Size ---------------------------------------------------------------- -Param 64 2 32 -Local 64 1 64 -ForeignItem 72 1 72 -FieldDef 96 2 48 -Arm 96 2 48 -Stmt 96 3 32 -FnDecl 120 3 40 -Lifetime 128 4 32 -Variant 160 2 80 -ImplItem 176 2 88 -GenericBound 192 4 48 -TraitItem 192 2 96 -WherePredicate 216 3 72 -Block 288 6 48 -QPath 408 17 24 -Pat 440 5 88 -Attribute 608 4 152 -Expr 672 12 56 -Item 960 12 80 -Ty 1_152 16 72 -Path 1_296 27 48 -PathSegment 2_240 40 56 +Param 64 ( 0.7%) 2 32 +Local 64 ( 0.7%) 1 64 +ForeignItem 72 ( 0.7%) 1 72 +FieldDef 96 ( 1.0%) 2 48 +Arm 96 ( 1.0%) 2 48 +Stmt 96 ( 1.0%) 3 32 +FnDecl 120 ( 1.2%) 3 40 +Lifetime 128 ( 1.3%) 4 32 +Variant 160 ( 1.6%) 2 80 +ImplItem 176 ( 1.8%) 2 88 +GenericBound 192 ( 2.0%) 4 48 +TraitItem 192 ( 2.0%) 2 96 +WherePredicate 216 ( 2.2%) 3 72 +Block 288 ( 3.0%) 6 48 +QPath 408 ( 4.2%) 17 24 +Pat 440 ( 4.5%) 5 88 +Attribute 608 ( 6.2%) 4 152 +Expr 672 ( 6.9%) 12 56 +Item 960 ( 9.9%) 12 80 +Ty 1_152 (11.8%) 16 72 +Path 1_296 (13.3%) 27 48 +PathSegment 2_240 (23.0%) 40 56 ---------------------------------------------------------------- -Total 9_736 +Total 9_736 From 4f8a1702bab38730bf2386e2e3df57b63a768077 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 11 Aug 2022 14:37:21 +1000 Subject: [PATCH 19/21] Add a second level to the AST size reporting. This tells you which variants of the enums are most common, which is very useful. I've only done it for the AST for now, HIR can be done later. --- compiler/rustc_passes/src/hir_stats.rs | 218 +++++++++++++++++++++---- src/test/ui/stats/hir-stats.rs | 4 +- src/test/ui/stats/hir-stats.stderr | 60 +++++++ 3 files changed, 246 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 0c6c1d1aa2b8e..ec070e6a9c5c6 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -21,11 +21,28 @@ enum Id { None, } -struct NodeData { +struct NodeStats { count: usize, size: usize, } +impl NodeStats { + fn new() -> NodeStats { + NodeStats { count: 0, size: 0 } + } +} + +struct Node { + stats: NodeStats, + subnodes: FxHashMap<&'static str, NodeStats>, +} + +impl Node { + fn new() -> Node { + Node { stats: NodeStats::new(), subnodes: FxHashMap::default() } + } +} + /// This type measures the size of AST and HIR nodes, by implementing the AST /// and HIR `Visitor` traits. But we don't measure every visited type because /// that could cause double counting. @@ -45,14 +62,14 @@ struct NodeData { /// unfortunate. struct StatCollector<'k> { krate: Option>, - data: FxHashMap<&'static str, NodeData>, + nodes: FxHashMap<&'static str, Node>, seen: FxHashSet, } pub fn print_hir_stats(tcx: TyCtxt<'_>) { let mut collector = StatCollector { krate: Some(tcx.hir()), - data: FxHashMap::default(), + nodes: FxHashMap::default(), seen: FxHashSet::default(), }; tcx.hir().walk_toplevel_module(&mut collector); @@ -64,47 +81,82 @@ pub fn print_ast_stats(krate: &ast::Crate, title: &str) { use rustc_ast::visit::Visitor; let mut collector = - StatCollector { krate: None, data: FxHashMap::default(), seen: FxHashSet::default() }; + StatCollector { krate: None, nodes: FxHashMap::default(), seen: FxHashSet::default() }; collector.visit_crate(krate); collector.print(title); } impl<'k> StatCollector<'k> { - fn record(&mut self, label: &'static str, id: Id, node: &T) { + // Record a top-level node. + fn record(&mut self, label: &'static str, id: Id, val: &T) { + self.record_inner(label, None, id, val); + } + + // Record a two-level entry, with a top-level enum type and a variant. + fn record_variant(&mut self, label1: &'static str, label2: &'static str, id: Id, val: &T) { + self.record_inner(label1, Some(label2), id, val); + } + + fn record_inner( + &mut self, + label1: &'static str, + label2: Option<&'static str>, + id: Id, + val: &T, + ) { if id != Id::None && !self.seen.insert(id) { return; } - let entry = self.data.entry(label).or_insert(NodeData { count: 0, size: 0 }); + let node = self.nodes.entry(label1).or_insert(Node::new()); + node.stats.count += 1; + node.stats.size = std::mem::size_of_val(val); - entry.count += 1; - entry.size = std::mem::size_of_val(node); + if let Some(label2) = label2 { + let subnode = node.subnodes.entry(label2).or_insert(NodeStats::new()); + subnode.count += 1; + subnode.size = std::mem::size_of_val(val); + } } fn print(&self, title: &str) { - let mut stats: Vec<_> = self.data.iter().collect(); - - stats.sort_by_key(|&(_, ref d)| d.count * d.size); + let mut nodes: Vec<_> = self.nodes.iter().collect(); + nodes.sort_by_key(|&(_, ref node)| node.stats.count * node.stats.size); - let total_size = stats.iter().map(|(_, data)| data.count * data.size).sum(); + let total_size = nodes.iter().map(|(_, node)| node.stats.count * node.stats.size).sum(); eprintln!("\n{}\n", title); eprintln!("{:<18}{:>18}{:>14}{:>14}", "Name", "Accumulated Size", "Count", "Item Size"); eprintln!("----------------------------------------------------------------"); - let percent = |m, n| { (m * 100) as f64 / n as f64 }; + let percent = |m, n| (m * 100) as f64 / n as f64; - for (label, data) in stats { - let size = data.count * data.size; + for (label, node) in nodes { + let size = node.stats.count * node.stats.size; eprintln!( "{:<18}{:>10} ({:4.1}%){:>14}{:>14}", label, to_readable_str(size), percent(size, total_size), - to_readable_str(data.count), - to_readable_str(data.size) + to_readable_str(node.stats.count), + to_readable_str(node.stats.size) ); + if !node.subnodes.is_empty() { + let mut subnodes: Vec<_> = node.subnodes.iter().collect(); + subnodes.sort_by_key(|&(_, ref subnode)| subnode.count * subnode.size); + + for (label, subnode) in subnodes { + let size = subnode.count * subnode.size; + eprintln!( + "- {:<18}{:>10} ({:4.1}%){:>14}", + label, + to_readable_str(size), + percent(size, total_size), + to_readable_str(subnode.count), + ); + } + } } eprintln!("----------------------------------------------------------------"); eprintln!("{:<18}{:>10}\n", "Total", to_readable_str(total_size)); @@ -268,14 +320,54 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } } +// Used to avoid boilerplate for types with many variants. +macro_rules! record_variants { + ( + ($self:ident, $val:expr, $kind:expr, $ty:ty, $tykind:ident), // mandatory pieces + [$($variant:ident),*] + ) => { + match $kind { + $( + ast::$tykind::$variant { .. } => { + $self.record_variant(stringify!($ty), stringify!($variant), Id::None, $val) + } + )* + } + }; +} + impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) { - self.record("ForeignItem", Id::None, i); + record_variants!( + (self, i, i.kind, ForeignItem, ForeignItemKind), + [Static, Fn, TyAlias, MacCall] + ); ast_visit::walk_foreign_item(self, i) } fn visit_item(&mut self, i: &'v ast::Item) { - self.record("Item", Id::None, i); + record_variants!( + (self, i, i.kind, Item, ItemKind), + [ + ExternCrate, + Use, + Static, + Const, + Fn, + Mod, + ForeignMod, + GlobalAsm, + TyAlias, + Enum, + Struct, + Union, + Trait, + TraitAlias, + Impl, + MacCall, + MacroDef + ] + ); ast_visit::walk_item(self, i) } @@ -290,7 +382,10 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_stmt(&mut self, s: &'v ast::Stmt) { - self.record("Stmt", Id::None, s); + record_variants!( + (self, s, s.kind, Stmt, StmtKind), + [Local, Item, Expr, Semi, Empty, MacCall] + ); ast_visit::walk_stmt(self, s) } @@ -305,17 +400,66 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_pat(&mut self, p: &'v ast::Pat) { - self.record("Pat", Id::None, p); + record_variants!( + (self, p, p.kind, Pat, PatKind), + [ + Wild, + Ident, + Struct, + TupleStruct, + Or, + Path, + Tuple, + Box, + Ref, + Lit, + Range, + Slice, + Rest, + Paren, + MacCall + ] + ); ast_visit::walk_pat(self, p) } - fn visit_expr(&mut self, ex: &'v ast::Expr) { - self.record("Expr", Id::None, ex); - ast_visit::walk_expr(self, ex) + fn visit_expr(&mut self, e: &'v ast::Expr) { + record_variants!( + (self, e, e.kind, Expr, ExprKind), + [ + Box, Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let, + If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign, + AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret, + InlineAsm, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, Err + ] + ); + ast_visit::walk_expr(self, e) } fn visit_ty(&mut self, t: &'v ast::Ty) { - self.record("Ty", Id::None, t); + record_variants!( + (self, t, t.kind, Ty, TyKind), + [ + Slice, + Array, + Ptr, + Rptr, + BareFn, + Never, + Tup, + Path, + TraitObject, + ImplTrait, + Paren, + Typeof, + Infer, + ImplicitSelf, + MacCall, + Err, + CVarArgs + ] + ); + ast_visit::walk_ty(self, t) } @@ -325,7 +469,10 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) { - self.record("WherePredicate", Id::None, p); + record_variants!( + (self, p, p, WherePredicate, WherePredicate), + [BoundPredicate, RegionPredicate, EqPredicate] + ); ast_visit::walk_where_predicate(self, p) } @@ -334,14 +481,17 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_fn(self, fk, s) } - fn visit_assoc_item(&mut self, item: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) { - self.record("AssocItem", Id::None, item); - ast_visit::walk_assoc_item(self, item, ctxt); + fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) { + record_variants!( + (self, i, i.kind, AssocItem, AssocItemKind), + [Const, Fn, TyAlias, MacCall] + ); + ast_visit::walk_assoc_item(self, i, ctxt); } - fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound, _ctxt: BoundKind) { - self.record("GenericBound", Id::None, bounds); - ast_visit::walk_param_bound(self, bounds) + fn visit_param_bound(&mut self, b: &'v ast::GenericBound, _ctxt: BoundKind) { + record_variants!((self, b, b, GenericBound, GenericBound), [Trait, Outlives]); + ast_visit::walk_param_bound(self, b) } fn visit_field_def(&mut self, s: &'v ast::FieldDef) { @@ -369,12 +519,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { // common, so we implement `visit_generic_args` and tolerate the double // counting in the former case. fn visit_generic_args(&mut self, sp: Span, g: &'v ast::GenericArgs) { - self.record("GenericArgs", Id::None, g); + record_variants!((self, g, g, GenericArgs, GenericArgs), [AngleBracketed, Parenthesized]); ast_visit::walk_generic_args(self, sp, g) } fn visit_attribute(&mut self, attr: &'v ast::Attribute) { - self.record("Attribute", Id::None, attr); + record_variants!((self, attr, attr.kind, Attribute, AttrKind), [Normal, DocComment]); ast_visit::walk_attribute(self, attr) } diff --git a/src/test/ui/stats/hir-stats.rs b/src/test/ui/stats/hir-stats.rs index 3c59ee22f24c5..a24b3ada57e59 100644 --- a/src/test/ui/stats/hir-stats.rs +++ b/src/test/ui/stats/hir-stats.rs @@ -2,8 +2,8 @@ // compile-flags: -Zhir-stats // only-x86_64 -// The aim here is to include at least one of every different type of AST/HIR -// node reported by `-Zhir-stats`. +// The aim here is to include at least one of every different type of top-level +// AST/HIR node reported by `-Zhir-stats`. #![allow(dead_code)] diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 132fff1972f4f..f4874408c9094 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -5,26 +5,55 @@ Name Accumulated Size Count Item Size ---------------------------------------------------------------- ExprField 48 ( 0.5%) 1 48 GenericArgs 64 ( 0.7%) 1 64 +- AngleBracketed 64 ( 0.7%) 1 Local 72 ( 0.8%) 1 72 WherePredicate 72 ( 0.8%) 1 72 +- BoundPredicate 72 ( 0.8%) 1 Crate 72 ( 0.8%) 1 72 Arm 96 ( 1.0%) 2 48 FieldDef 160 ( 1.7%) 2 80 ForeignItem 160 ( 1.7%) 1 160 +- Fn 160 ( 1.7%) 1 Stmt 160 ( 1.7%) 5 32 +- Local 32 ( 0.3%) 1 +- MacCall 32 ( 0.3%) 1 +- Expr 96 ( 1.0%) 3 Param 160 ( 1.7%) 4 40 FnDecl 200 ( 2.2%) 5 40 Variant 240 ( 2.6%) 2 120 Block 288 ( 3.1%) 6 48 Attribute 304 ( 3.3%) 2 152 +- Normal 152 ( 1.7%) 1 +- DocComment 152 ( 1.7%) 1 GenericBound 352 ( 3.8%) 4 88 +- Trait 352 ( 3.8%) 4 GenericParam 520 ( 5.7%) 5 104 AssocItem 640 ( 7.0%) 4 160 +- TyAlias 320 ( 3.5%) 2 +- Fn 320 ( 3.5%) 2 PathSegment 720 ( 7.9%) 30 24 Expr 832 ( 9.1%) 8 104 +- Path 104 ( 1.1%) 1 +- Match 104 ( 1.1%) 1 +- Struct 104 ( 1.1%) 1 +- Lit 208 ( 2.3%) 2 +- Block 312 ( 3.4%) 3 Pat 840 ( 9.2%) 7 120 +- Struct 120 ( 1.3%) 1 +- Wild 120 ( 1.3%) 1 +- Ident 600 ( 6.6%) 5 Ty 1_344 (14.7%) 14 96 +- Rptr 96 ( 1.0%) 1 +- Ptr 96 ( 1.0%) 1 +- ImplicitSelf 192 ( 2.1%) 2 +- Path 960 (10.5%) 10 Item 1_800 (19.7%) 9 200 +- Trait 200 ( 2.2%) 1 +- Enum 200 ( 2.2%) 1 +- ForeignMod 200 ( 2.2%) 1 +- Impl 200 ( 2.2%) 1 +- Fn 400 ( 4.4%) 2 +- Use 600 ( 6.6%) 3 ---------------------------------------------------------------- Total 9_144 @@ -35,27 +64,58 @@ Name Accumulated Size Count Item Size ---------------------------------------------------------------- ExprField 48 ( 0.5%) 1 48 GenericArgs 64 ( 0.6%) 1 64 +- AngleBracketed 64 ( 0.6%) 1 Local 72 ( 0.7%) 1 72 WherePredicate 72 ( 0.7%) 1 72 +- BoundPredicate 72 ( 0.7%) 1 Crate 72 ( 0.7%) 1 72 Arm 96 ( 0.9%) 2 48 InlineAsm 120 ( 1.2%) 1 120 FieldDef 160 ( 1.6%) 2 80 ForeignItem 160 ( 1.6%) 1 160 +- Fn 160 ( 1.6%) 1 Stmt 160 ( 1.6%) 5 32 +- Local 32 ( 0.3%) 1 +- Semi 32 ( 0.3%) 1 +- Expr 96 ( 0.9%) 3 Param 160 ( 1.6%) 4 40 FnDecl 200 ( 2.0%) 5 40 Variant 240 ( 2.4%) 2 120 Block 288 ( 2.8%) 6 48 GenericBound 352 ( 3.5%) 4 88 +- Trait 352 ( 3.5%) 4 GenericParam 520 ( 5.1%) 5 104 Attribute 608 ( 6.0%) 4 152 +- DocComment 152 ( 1.5%) 1 +- Normal 456 ( 4.5%) 3 AssocItem 640 ( 6.3%) 4 160 +- TyAlias 320 ( 3.2%) 2 +- Fn 320 ( 3.2%) 2 PathSegment 792 ( 7.8%) 33 24 Pat 840 ( 8.3%) 7 120 +- Struct 120 ( 1.2%) 1 +- Wild 120 ( 1.2%) 1 +- Ident 600 ( 5.9%) 5 Expr 936 ( 9.2%) 9 104 +- Path 104 ( 1.0%) 1 +- Match 104 ( 1.0%) 1 +- Struct 104 ( 1.0%) 1 +- InlineAsm 104 ( 1.0%) 1 +- Lit 208 ( 2.1%) 2 +- Block 312 ( 3.1%) 3 Ty 1_344 (13.2%) 14 96 +- Rptr 96 ( 0.9%) 1 +- Ptr 96 ( 0.9%) 1 +- ImplicitSelf 192 ( 1.9%) 2 +- Path 960 ( 9.5%) 10 Item 2_200 (21.7%) 11 200 +- Trait 200 ( 2.0%) 1 +- Enum 200 ( 2.0%) 1 +- ExternCrate 200 ( 2.0%) 1 +- ForeignMod 200 ( 2.0%) 1 +- Impl 200 ( 2.0%) 1 +- Fn 400 ( 3.9%) 2 +- Use 800 ( 7.9%) 4 ---------------------------------------------------------------- Total 10_144 From a72f0c2e0716fbfc4095c76c999de18e1c685154 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 11 Aug 2022 13:02:19 +0200 Subject: [PATCH 20/21] Add instructions on how to update the browser-ui-test version --- src/bootstrap/test.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index ed1d883d0dca6..baad0c75295a5 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -924,6 +924,11 @@ fn compare_browser_ui_test_version(installed_version: &str, src: &Path) { one used in the CI (`{}`)", installed_version, v ); + eprintln!( + "You can install this version using `npm update browser-ui-test` or by using \ + `npm install browser-ui-test@{}`", + v, + ); } } Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e), From 46af79c0ab545589d1a6569fb773c544a8d51547 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 11 Aug 2022 13:20:18 +0200 Subject: [PATCH 21/21] Improve error message when browser-ui-test crashes --- src/tools/rustdoc-gui/tester.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index a512185036915..70d5f94472f6b 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -201,6 +201,19 @@ async function main(argv) { process.setMaxListeners(opts["jobs"] + 1); } + // We catch this "event" to display a nicer message in case of unexpected exit (because of a + // missing `--no-sandbox`). + const exitHandling = (code) => { + if (!opts["no_sandbox"]) { + console.log(""); + console.log( + "`browser-ui-test` crashed unexpectedly. Please try again with adding `--test-args \ +--no-sandbox` at the end. For example: `x.py test src/test/rustdoc-gui --test-args --no-sandbox`"); + console.log(""); + } + }; + process.on('exit', exitHandling); + const tests_queue = []; let results = { successful: [], @@ -247,6 +260,9 @@ async function main(argv) { } status_bar.finish(); + // We don't need this listener anymore. + process.removeListener("exit", exitHandling); + if (debug) { results.successful.sort(by_filename); results.successful.forEach(r => {