Skip to content

Commit a4e2389

Browse files
authored
Unrolled build for rust-lang#137465
Rollup merge of rust-lang#137465 - Zalathar:visit-primary, r=oli-obk 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 --- There should be no user-visible change in compiler output.
2 parents 8279176 + 5434242 commit a4e2389

14 files changed

+699
-156
lines changed

compiler/rustc_middle/src/mir/mod.rs

+3-82
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ use crate::mir::interpret::{AllocRange, Scalar};
3333
use crate::ty::codec::{TyDecoder, TyEncoder};
3434
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
3535
use crate::ty::{
36-
self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt,
37-
TypeVisitableExt, TypingEnv, UserTypeAnnotationIndex,
36+
self, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypeVisitableExt,
37+
TypingEnv, UserTypeAnnotationIndex,
3838
};
3939

4040
mod basic_blocks;
@@ -1482,53 +1482,10 @@ pub struct UserTypeProjections {
14821482
pub contents: Vec<UserTypeProjection>,
14831483
}
14841484

1485-
impl<'tcx> UserTypeProjections {
1486-
pub fn none() -> Self {
1487-
UserTypeProjections { contents: vec![] }
1488-
}
1489-
1490-
pub fn is_empty(&self) -> bool {
1491-
self.contents.is_empty()
1492-
}
1493-
1485+
impl UserTypeProjections {
14941486
pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator {
14951487
self.contents.iter()
14961488
}
1497-
1498-
pub fn push_user_type(mut self, base_user_type: UserTypeAnnotationIndex) -> Self {
1499-
self.contents.push(UserTypeProjection { base: base_user_type, projs: vec![] });
1500-
self
1501-
}
1502-
1503-
fn map_projections(mut self, f: impl FnMut(UserTypeProjection) -> UserTypeProjection) -> Self {
1504-
self.contents = self.contents.into_iter().map(f).collect();
1505-
self
1506-
}
1507-
1508-
pub fn index(self) -> Self {
1509-
self.map_projections(|pat_ty_proj| pat_ty_proj.index())
1510-
}
1511-
1512-
pub fn subslice(self, from: u64, to: u64) -> Self {
1513-
self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
1514-
}
1515-
1516-
pub fn deref(self) -> Self {
1517-
self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
1518-
}
1519-
1520-
pub fn leaf(self, field: FieldIdx) -> Self {
1521-
self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
1522-
}
1523-
1524-
pub fn variant(
1525-
self,
1526-
adt_def: AdtDef<'tcx>,
1527-
variant_index: VariantIdx,
1528-
field_index: FieldIdx,
1529-
) -> Self {
1530-
self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field_index))
1531-
}
15321489
}
15331490

15341491
/// Encodes the effect of a user-supplied type annotation on the
@@ -1553,42 +1510,6 @@ pub struct UserTypeProjection {
15531510
pub projs: Vec<ProjectionKind>,
15541511
}
15551512

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

compiler/rustc_middle/src/thir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -783,8 +783,12 @@ pub enum PatKind<'tcx> {
783783
var: LocalVarId,
784784
ty: Ty<'tcx>,
785785
subpattern: Option<Box<Pat<'tcx>>>,
786+
786787
/// Is this the leftmost occurrence of the binding, i.e., is `var` the
787788
/// `HirId` of this pattern?
789+
///
790+
/// (The same binding can occur multiple times in different branches of
791+
/// an or-pattern, but only one of them will be primary.)
788792
is_primary: bool,
789793
},
790794

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)