Skip to content

Commit e7489a4

Browse files
committed
Build UserTypeProjections lazily when visiting bindings
1 parent f2e128f commit e7489a4

File tree

3 files changed

+178
-111
lines changed

3 files changed

+178
-111
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_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,
@@ -28,13 +34,9 @@ use crate::builder::{
2834
mod match_pair;
2935
mod simplify;
3036
mod test;
37+
mod user_ty;
3138
mod util;
3239

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

767770
this.declare_binding(
768771
source_info,
@@ -771,7 +774,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
771774
mode,
772775
var,
773776
ty,
774-
user_ty,
777+
user_tys,
775778
ArmHasGuard(guard.is_some()),
776779
opt_match_place.map(|(x, y)| (x.cloned(), y)),
777780
pattern.span,
@@ -875,29 +878,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
875878
fn visit_primary_bindings_special(
876879
&mut self,
877880
pattern: &Pat<'tcx>,
878-
pattern_user_ty: UserTypeProjections,
881+
user_tys: &ProjectedUserTypesNode<'_>,
879882
f: &mut impl FnMut(
880883
&mut Self,
881884
Symbol,
882885
BindingMode,
883886
LocalVarId,
884887
Span,
885888
Ty<'tcx>,
886-
UserTypeProjections,
889+
&ProjectedUserTypesNode<'_>,
887890
),
888891
) {
889892
// Avoid having to write the full method name at each recursive call.
890-
let visit_subpat = |this: &mut Self, subpat, user_tys, f: &mut _| {
893+
let visit_subpat = |this: &mut Self, subpat, user_tys: &_, f: &mut _| {
891894
this.visit_primary_bindings_special(subpat, user_tys, f)
892895
};
893896

894897
match pattern.kind {
895898
PatKind::Binding { name, mode, var, ty, ref subpattern, is_primary, .. } => {
896899
if is_primary {
897-
f(self, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
900+
f(self, name, mode, var, pattern.span, ty, user_tys);
898901
}
899902
if let Some(subpattern) = subpattern.as_ref() {
900-
visit_subpat(self, subpattern, pattern_user_ty, f);
903+
visit_subpat(self, subpattern, user_tys, f);
901904
}
902905
}
903906

@@ -906,13 +909,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
906909
let from = u64::try_from(prefix.len()).unwrap();
907910
let to = u64::try_from(suffix.len()).unwrap();
908911
for subpattern in prefix.iter() {
909-
visit_subpat(self, subpattern, pattern_user_ty.clone().index(), f);
912+
visit_subpat(self, subpattern, &user_tys.index(), f);
910913
}
911914
if let Some(subpattern) = slice {
912-
visit_subpat(self, subpattern, pattern_user_ty.clone().subslice(from, to), f);
915+
visit_subpat(self, subpattern, &user_tys.subslice(from, to), f);
913916
}
914917
for subpattern in suffix.iter() {
915-
visit_subpat(self, subpattern, pattern_user_ty.clone().index(), f);
918+
visit_subpat(self, subpattern, &user_tys.index(), f);
916919
}
917920
}
918921

@@ -923,11 +926,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
923926
| PatKind::Error(_) => {}
924927

925928
PatKind::Deref { ref subpattern } => {
926-
visit_subpat(self, subpattern, pattern_user_ty.deref(), f);
929+
visit_subpat(self, subpattern, &user_tys.deref(), f);
927930
}
928931

929932
PatKind::DerefPattern { ref subpattern, .. } => {
930-
visit_subpat(self, subpattern, UserTypeProjections::none(), f);
933+
visit_subpat(self, subpattern, &ProjectedUserTypesNode::None, f);
931934
}
932935

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

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

951957
PatKind::ExpandedConstant { ref subpattern, .. } => {
952-
visit_subpat(self, subpattern, pattern_user_ty, f)
958+
visit_subpat(self, subpattern, user_tys, f)
953959
}
954960

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

963969
PatKind::Variant { adt_def, args: _, variant_index, ref subpatterns } => {
964970
for subpattern in subpatterns {
965-
let subpattern_user_ty =
966-
pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field);
967-
visit_subpat(self, &subpattern.pattern, subpattern_user_ty, f);
971+
let subpattern_user_tys =
972+
user_tys.variant(adt_def, variant_index, subpattern.field);
973+
visit_subpat(self, &subpattern.pattern, &subpattern_user_tys, f);
968974
}
969975
}
970976
PatKind::Or { ref pats } => {
@@ -973,7 +979,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
973979
// `let (x | y) = ...`, the primary binding of `y` occurs in
974980
// the right subpattern
975981
for subpattern in pats.iter() {
976-
visit_subpat(self, subpattern, pattern_user_ty.clone(), f);
982+
visit_subpat(self, subpattern, user_tys, f);
977983
}
978984
}
979985
}
@@ -2781,7 +2787,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
27812787
mode: BindingMode,
27822788
var_id: LocalVarId,
27832789
var_ty: Ty<'tcx>,
2784-
user_ty: UserTypeProjections,
2790+
user_ty: Option<Box<UserTypeProjections>>,
27852791
has_guard: ArmHasGuard,
27862792
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
27872793
pat_span: Span,
@@ -2791,7 +2797,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
27912797
let local = LocalDecl {
27922798
mutability: mode.1,
27932799
ty: var_ty,
2794-
user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
2800+
user_ty,
27952801
source_info,
27962802
local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var(
27972803
VarBindingForm {

0 commit comments

Comments
 (0)