From 9e76fcc468f57a1040a85cc195374923be414401 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 Jun 2022 10:43:47 +1000 Subject: [PATCH 1/2] Change `Search::infcx` to `tcx`. Because the `infcx` isn't needed. This removes one lifetime from `Search`. --- .../src/traits/structural_match.rs | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index bc2ce31df6d93..8db1d4cfbe8b8 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -60,7 +60,7 @@ pub fn search_for_structural_match_violation<'tcx>( ) -> Option> { // FIXME: we should instead pass in an `infcx` from the outside. tcx.infer_ctxt().enter(|infcx| { - ty.visit_with(&mut Search { infcx, span, seen: FxHashSet::default() }).break_value() + ty.visit_with(&mut Search { tcx: infcx.tcx, span, seen: FxHashSet::default() }).break_value() }) } @@ -114,27 +114,23 @@ fn type_marked_structural<'tcx>( /// This implements the traversal over the structure of a given type to try to /// find instances of ADTs (specifically structs or enums) that do not implement /// the structural-match traits (`StructuralPartialEq` and `StructuralEq`). -struct Search<'a, 'tcx> { +struct Search<'tcx> { span: Span, - infcx: InferCtxt<'a, 'tcx>, + tcx: TyCtxt<'tcx>, /// Tracks ADTs previously encountered during search, so that /// we will not recur on them again. seen: FxHashSet, } -impl<'a, 'tcx> Search<'a, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - +impl<'tcx> Search<'tcx> { fn type_marked_structural(&self, adt_ty: Ty<'tcx>) -> bool { - adt_ty.is_structural_eq_shallow(self.tcx()) + adt_ty.is_structural_eq_shallow(self.tcx) } } -impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { +impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { type BreakTy = NonStructuralMatchTy<'tcx>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { @@ -193,7 +189,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { return ControlFlow::CONTINUE; } ty::Array(_, n) - if { n.try_eval_usize(self.tcx(), ty::ParamEnv::reveal_all()) == Some(0) } => + if { n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) } => { // rust-lang/rust#62336: ignore type of contents // for empty array. @@ -214,7 +210,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { bug!("unexpected type during structural-match checking: {:?}", ty); } ty::Error(_) => { - self.tcx().sess.delay_span_bug(self.span, "ty::Error in structural-match check"); + self.tcx.sess.delay_span_bug(self.span, "ty::Error in structural-match check"); // We still want to check other types after encountering an error, // as this may still emit relevant errors. return ControlFlow::CONTINUE; @@ -244,9 +240,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { // even though we skip super_visit_with, we must recur on // fields of ADT. - let tcx = self.tcx(); + let tcx = self.tcx; adt_def.all_fields().map(|field| field.ty(tcx, substs)).try_for_each(|field_ty| { - let ty = self.tcx().normalize_erasing_regions(ty::ParamEnv::empty(), field_ty); + let ty = self.tcx.normalize_erasing_regions(ty::ParamEnv::empty(), field_ty); debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty); ty.visit_with(self) }) From 687e391bc3a9682b6fe956a2e39a8a3935047158 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 Jun 2022 11:56:28 +1000 Subject: [PATCH 2/2] Avoid constructing an unnecessary `InferCtxt`. Currently, `search_for_structural_match_violation` constructs an `infcx` from a `tcx` and then only uses the `tcx` within the `infcx`. This is wasteful because `infcx` is a big type. This commit changes it to use the `tcx` directly. When compiling `pest-2.1.3`, this changes the memcpy stats reported by DHAT for a `check full` build from this: ``` 433,008,916 bytes (100%, 99,787.93/Minstr) in 2,148,668 blocks (100%, 495.17/Minstr), avg size 201.52 bytes ``` to this: ``` 101,422,347 bytes (99.98%, 25,243.59/Minstr) in 1,318,407 blocks (99.96%, 328.15/Minstr), avg size 76.93 bytes ``` This translates to a 4.3% reduction in instruction counts. --- .../rustc_trait_selection/src/traits/structural_match.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 8db1d4cfbe8b8..725df69974c9c 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -58,10 +58,7 @@ pub fn search_for_structural_match_violation<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ) -> Option> { - // FIXME: we should instead pass in an `infcx` from the outside. - tcx.infer_ctxt().enter(|infcx| { - ty.visit_with(&mut Search { tcx: infcx.tcx, span, seen: FxHashSet::default() }).break_value() - }) + ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default() }).break_value() } /// This method returns true if and only if `adt_ty` itself has been marked as