Skip to content

Commit 5434242

Browse files
committed
Build UserTypeProjections lazily when visiting bindings
1 parent 7805b46 commit 5434242

File tree

3 files changed

+179
-112
lines changed

3 files changed

+179
-112
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_mir_build/src/builder/matches/mod.rs

+36-30
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
//! This also includes code for pattern bindings in `let` statements and
66
//! function parameters.
77
8+
use std::assert_matches::assert_matches;
9+
use std::borrow::Borrow;
10+
use std::mem;
11+
use std::sync::Arc;
12+
813
use rustc_abi::VariantIdx;
914
use rustc_data_structures::fx::FxIndexMap;
1015
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -19,6 +24,7 @@ use tracing::{debug, instrument};
1924

2025
use crate::builder::ForGuard::{self, OutsideGuard, RefWithinGuard};
2126
use crate::builder::expr::as_place::PlaceBuilder;
27+
use crate::builder::matches::user_ty::ProjectedUserTypesNode;
2228
use crate::builder::scope::DropKind;
2329
use crate::builder::{
2430
BlockAnd, BlockAndExtension, Builder, GuardFrame, GuardFrameLocal, LocalsForNode,
@@ -27,13 +33,9 @@ use crate::builder::{
2733
// helper functions, broken out by category:
2834
mod match_pair;
2935
mod test;
36+
mod user_ty;
3037
mod util;
3138

32-
use std::assert_matches::assert_matches;
33-
use std::borrow::Borrow;
34-
use std::mem;
35-
use std::sync::Arc;
36-
3739
/// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded
3840
/// to recursive invocations.
3941
#[derive(Clone, Copy)]
@@ -757,11 +759,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
757759
) -> Option<SourceScope> {
758760
self.visit_primary_bindings_special(
759761
pattern,
760-
UserTypeProjections::none(),
761-
&mut |this, name, mode, var, span, ty, user_ty| {
762+
&ProjectedUserTypesNode::None,
763+
&mut |this, name, mode, var, span, ty, user_tys| {
762764
let vis_scope = *visibility_scope
763765
.get_or_insert_with(|| this.new_source_scope(scope_span, LintLevel::Inherited));
764766
let source_info = SourceInfo { span, scope: this.source_scope };
767+
let user_tys = user_tys.build_user_type_projections();
765768

766769
this.declare_binding(
767770
source_info,
@@ -770,7 +773,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
770773
mode,
771774
var,
772775
ty,
773-
user_ty,
776+
user_tys,
774777
ArmHasGuard(guard.is_some()),
775778
opt_match_place.map(|(x, y)| (x.cloned(), y)),
776779
pattern.span,
@@ -874,29 +877,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
874877
fn visit_primary_bindings_special(
875878
&mut self,
876879
pattern: &Pat<'tcx>,
877-
pattern_user_ty: UserTypeProjections,
880+
user_tys: &ProjectedUserTypesNode<'_>,
878881
f: &mut impl FnMut(
879882
&mut Self,
880883
Symbol,
881884
BindingMode,
882885
LocalVarId,
883886
Span,
884887
Ty<'tcx>,
885-
UserTypeProjections,
888+
&ProjectedUserTypesNode<'_>,
886889
),
887890
) {
888891
// Avoid having to write the full method name at each recursive call.
889-
let visit_subpat = |this: &mut Self, subpat, user_tys, f: &mut _| {
892+
let visit_subpat = |this: &mut Self, subpat, user_tys: &_, f: &mut _| {
890893
this.visit_primary_bindings_special(subpat, user_tys, f)
891894
};
892895

893896
match pattern.kind {
894897
PatKind::Binding { name, mode, var, ty, ref subpattern, is_primary, .. } => {
895898
if is_primary {
896-
f(self, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
899+
f(self, name, mode, var, pattern.span, ty, user_tys);
897900
}
898901
if let Some(subpattern) = subpattern.as_ref() {
899-
visit_subpat(self, subpattern, pattern_user_ty, f);
902+
visit_subpat(self, subpattern, user_tys, f);
900903
}
901904
}
902905

@@ -905,13 +908,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
905908
let from = u64::try_from(prefix.len()).unwrap();
906909
let to = u64::try_from(suffix.len()).unwrap();
907910
for subpattern in prefix.iter() {
908-
visit_subpat(self, subpattern, pattern_user_ty.clone().index(), f);
911+
visit_subpat(self, subpattern, &user_tys.index(), f);
909912
}
910913
if let Some(subpattern) = slice {
911-
visit_subpat(self, subpattern, pattern_user_ty.clone().subslice(from, to), f);
914+
visit_subpat(self, subpattern, &user_tys.subslice(from, to), f);
912915
}
913916
for subpattern in suffix.iter() {
914-
visit_subpat(self, subpattern, pattern_user_ty.clone().index(), f);
917+
visit_subpat(self, subpattern, &user_tys.index(), f);
915918
}
916919
}
917920

@@ -922,11 +925,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
922925
| PatKind::Error(_) => {}
923926

924927
PatKind::Deref { ref subpattern } => {
925-
visit_subpat(self, subpattern, pattern_user_ty.deref(), f);
928+
visit_subpat(self, subpattern, &user_tys.deref(), f);
926929
}
927930

928931
PatKind::DerefPattern { ref subpattern, .. } => {
929-
visit_subpat(self, subpattern, UserTypeProjections::none(), f);
932+
visit_subpat(self, subpattern, &ProjectedUserTypesNode::None, f);
930933
}
931934

932935
PatKind::AscribeUserType {
@@ -942,28 +945,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
942945
// Note that the variance doesn't apply here, as we are tracking the effect
943946
// of `user_ty` on any bindings contained with subpattern.
944947

948+
// Caution: Pushing this user type here is load-bearing even for
949+
// patterns containing no bindings, to ensure that the type ends
950+
// up represented in MIR _somewhere_.
945951
let base_user_ty = self.canonical_user_type_annotations.push(annotation.clone());
946-
let subpattern_user_ty = pattern_user_ty.push_user_type(base_user_ty);
947-
visit_subpat(self, subpattern, subpattern_user_ty, f)
952+
let subpattern_user_tys = user_tys.push_user_type(base_user_ty);
953+
visit_subpat(self, subpattern, &subpattern_user_tys, f)
948954
}
949955

950956
PatKind::ExpandedConstant { ref subpattern, .. } => {
951-
visit_subpat(self, subpattern, pattern_user_ty, f)
957+
visit_subpat(self, subpattern, user_tys, f)
952958
}
953959

954960
PatKind::Leaf { ref subpatterns } => {
955961
for subpattern in subpatterns {
956-
let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field);
957-
debug!("visit_primary_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
958-
visit_subpat(self, &subpattern.pattern, subpattern_user_ty, f);
962+
let subpattern_user_tys = user_tys.leaf(subpattern.field);
963+
debug!("visit_primary_bindings: subpattern_user_tys={subpattern_user_tys:?}");
964+
visit_subpat(self, &subpattern.pattern, &subpattern_user_tys, f);
959965
}
960966
}
961967

962968
PatKind::Variant { adt_def, args: _, variant_index, ref subpatterns } => {
963969
for subpattern in subpatterns {
964-
let subpattern_user_ty =
965-
pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field);
966-
visit_subpat(self, &subpattern.pattern, subpattern_user_ty, f);
970+
let subpattern_user_tys =
971+
user_tys.variant(adt_def, variant_index, subpattern.field);
972+
visit_subpat(self, &subpattern.pattern, &subpattern_user_tys, f);
967973
}
968974
}
969975
PatKind::Or { ref pats } => {
@@ -972,7 +978,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
972978
// `let (x | y) = ...`, the primary binding of `y` occurs in
973979
// the right subpattern
974980
for subpattern in pats.iter() {
975-
visit_subpat(self, subpattern, pattern_user_ty.clone(), f);
981+
visit_subpat(self, subpattern, user_tys, f);
976982
}
977983
}
978984
}
@@ -2764,7 +2770,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
27642770
mode: BindingMode,
27652771
var_id: LocalVarId,
27662772
var_ty: Ty<'tcx>,
2767-
user_ty: UserTypeProjections,
2773+
user_ty: Option<Box<UserTypeProjections>>,
27682774
has_guard: ArmHasGuard,
27692775
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
27702776
pat_span: Span,
@@ -2774,7 +2780,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
27742780
let local = LocalDecl {
27752781
mutability: mode.1,
27762782
ty: var_ty,
2777-
user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
2783+
user_ty,
27782784
source_info,
27792785
local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var(
27802786
VarBindingForm {

0 commit comments

Comments
 (0)