Skip to content

Commit cde7127

Browse files
committed
Auto merge of rust-lang#137465 - Zalathar:visit-primary, r=<try>
mir_build: Avoid some useless work when visiting "primary" bindings While looking over `visit_primary_bindings`, I noticed that it does a bunch of extra work to build up a collection of “user-type projections”, even though 2/3 of its call sites don't even use them. Those callers can get the same result via `thir::Pat::walk_always`. (And it turns out that doing so also avoids creating some redundant user-type entries in MIR for some binding constructs.) I also noticed that even when the user-type projections *are* used, the process of building them ends up eagerly cloning some nested vectors at every recursion step, even in cases where they won't be used because the current subpattern has no bindings. To avoid this, the visit method now assembles a linked list on the stack containing the information that *would* be needed to create projections, and only creates the concrete projections as needed when a primary binding is encountered. Some relevant prior PRs: - rust-lang#55274 - rust-lang@0bfe184 in rust-lang#55937
2 parents bca5f37 + 1d8a6e7 commit cde7127

14 files changed

+698
-155
lines changed

compiler/rustc_middle/src/mir/mod.rs

+2-81
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use crate::ty::codec::{TyDecoder, TyEncoder};
3535
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
3636
use crate::ty::visit::TypeVisitableExt;
3737
use crate::ty::{
38-
self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv,
38+
self, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv,
3939
UserTypeAnnotationIndex,
4040
};
4141

@@ -1475,53 +1475,10 @@ pub struct UserTypeProjections {
14751475
pub contents: Vec<UserTypeProjection>,
14761476
}
14771477

1478-
impl<'tcx> UserTypeProjections {
1479-
pub fn none() -> Self {
1480-
UserTypeProjections { contents: vec![] }
1481-
}
1482-
1483-
pub fn is_empty(&self) -> bool {
1484-
self.contents.is_empty()
1485-
}
1486-
1478+
impl UserTypeProjections {
14871479
pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator {
14881480
self.contents.iter()
14891481
}
1490-
1491-
pub fn push_user_type(mut self, base_user_type: UserTypeAnnotationIndex) -> Self {
1492-
self.contents.push(UserTypeProjection { base: base_user_type, projs: vec![] });
1493-
self
1494-
}
1495-
1496-
fn map_projections(mut self, f: impl FnMut(UserTypeProjection) -> UserTypeProjection) -> Self {
1497-
self.contents = self.contents.into_iter().map(f).collect();
1498-
self
1499-
}
1500-
1501-
pub fn index(self) -> Self {
1502-
self.map_projections(|pat_ty_proj| pat_ty_proj.index())
1503-
}
1504-
1505-
pub fn subslice(self, from: u64, to: u64) -> Self {
1506-
self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
1507-
}
1508-
1509-
pub fn deref(self) -> Self {
1510-
self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
1511-
}
1512-
1513-
pub fn leaf(self, field: FieldIdx) -> Self {
1514-
self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
1515-
}
1516-
1517-
pub fn variant(
1518-
self,
1519-
adt_def: AdtDef<'tcx>,
1520-
variant_index: VariantIdx,
1521-
field_index: FieldIdx,
1522-
) -> Self {
1523-
self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field_index))
1524-
}
15251482
}
15261483

15271484
/// Encodes the effect of a user-supplied type annotation on the
@@ -1546,42 +1503,6 @@ pub struct UserTypeProjection {
15461503
pub projs: Vec<ProjectionKind>,
15471504
}
15481505

1549-
impl UserTypeProjection {
1550-
pub(crate) fn index(mut self) -> Self {
1551-
self.projs.push(ProjectionElem::Index(()));
1552-
self
1553-
}
1554-
1555-
pub(crate) fn subslice(mut self, from: u64, to: u64) -> Self {
1556-
self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
1557-
self
1558-
}
1559-
1560-
pub(crate) fn deref(mut self) -> Self {
1561-
self.projs.push(ProjectionElem::Deref);
1562-
self
1563-
}
1564-
1565-
pub(crate) fn leaf(mut self, field: FieldIdx) -> Self {
1566-
self.projs.push(ProjectionElem::Field(field, ()));
1567-
self
1568-
}
1569-
1570-
pub(crate) fn variant(
1571-
mut self,
1572-
adt_def: AdtDef<'_>,
1573-
variant_index: VariantIdx,
1574-
field_index: FieldIdx,
1575-
) -> Self {
1576-
self.projs.push(ProjectionElem::Downcast(
1577-
Some(adt_def.variant(variant_index).name),
1578-
variant_index,
1579-
));
1580-
self.projs.push(ProjectionElem::Field(field_index, ()));
1581-
self
1582-
}
1583-
}
1584-
15851506
rustc_index::newtype_index! {
15861507
#[derive(HashStable)]
15871508
#[encodable]

compiler/rustc_middle/src/thir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -772,8 +772,12 @@ pub enum PatKind<'tcx> {
772772
var: LocalVarId,
773773
ty: Ty<'tcx>,
774774
subpattern: Option<Box<Pat<'tcx>>>,
775+
775776
/// Is this the leftmost occurrence of the binding, i.e., is `var` the
776777
/// `HirId` of this pattern?
778+
///
779+
/// (The same binding can occur multiple times in different branches of
780+
/// an or-pattern, but only one of them will be primary.)
777781
is_primary: bool,
778782
},
779783

compiler/rustc_mir_build/src/builder/block.rs

+19-27
Original file line numberDiff line numberDiff line change
@@ -199,19 +199,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
199199
None,
200200
Some((Some(&destination), initializer_span)),
201201
);
202-
this.visit_primary_bindings(
203-
pattern,
204-
UserTypeProjections::none(),
205-
&mut |this, _, _, node, span, _, _| {
206-
this.storage_live_binding(
207-
block,
208-
node,
209-
span,
210-
OutsideGuard,
211-
ScheduleDrops::Yes,
212-
);
213-
},
214-
);
202+
this.visit_primary_bindings(pattern, &mut |this, node, span| {
203+
this.storage_live_binding(
204+
block,
205+
node,
206+
span,
207+
OutsideGuard,
208+
ScheduleDrops::Yes,
209+
);
210+
});
215211
let else_block_span = this.thir[*else_block].span;
216212
let (matching, failure) =
217213
this.in_if_then_scope(last_remainder_scope, else_block_span, |this| {
@@ -295,20 +291,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
295291
});
296292

297293
debug!("ast_block_stmts: pattern={:?}", pattern);
298-
this.visit_primary_bindings(
299-
pattern,
300-
UserTypeProjections::none(),
301-
&mut |this, _, _, node, span, _, _| {
302-
this.storage_live_binding(
303-
block,
304-
node,
305-
span,
306-
OutsideGuard,
307-
ScheduleDrops::Yes,
308-
);
309-
this.schedule_drop_for_binding(node, span, OutsideGuard);
310-
},
311-
)
294+
this.visit_primary_bindings(pattern, &mut |this, node, span| {
295+
this.storage_live_binding(
296+
block,
297+
node,
298+
span,
299+
OutsideGuard,
300+
ScheduleDrops::Yes,
301+
);
302+
this.schedule_drop_for_binding(node, span, OutsideGuard);
303+
})
312304
}
313305

314306
// Enter the visibility scope, after evaluating the initializer.

0 commit comments

Comments
 (0)