Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit d4f8729

Browse files
committed
Delay use of Place in favor of PlaceBuilder
1 parent ec10b71 commit d4f8729

File tree

9 files changed

+139
-76
lines changed

9 files changed

+139
-76
lines changed

compiler/rustc_mir_build/src/build/block.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9494
)
9595
);
9696
}
97+
// ROX:
98+
//
99+
// Where the handling of destructure patterns start
100+
//
101+
// let (a, b, c, _ ) = something
102+
//
103+
// (a, b, c, _) is the pattern
104+
// something is the initializer
97105
StmtKind::Let { remainder_scope, init_scope, pattern, initializer, lint_level } => {
98106
let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
99107
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
@@ -125,6 +133,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
125133
ArmHasGuard(false),
126134
Some((None, initializer_span)),
127135
);
136+
// This is where we get into pattern handling of the let
137+
// statement
128138
this.expr_into_pattern(block, pattern.clone(), init)
129139
})
130140
}

compiler/rustc_mir_build/src/build/expr/as_place.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
1010
use rustc_middle::middle::region;
1111
use rustc_middle::mir::AssertKind::BoundsCheck;
1212
use rustc_middle::mir::*;
13+
use rustc_middle::ty::AdtDef;
1314
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance};
1415
use rustc_span::Span;
1516
use rustc_target::abi::VariantIdx;
1617

1718
use rustc_index::vec::Idx;
1819

1920
/// The "outermost" place that holds this value.
20-
#[derive(Copy, Clone, Debug)]
21+
#[derive(Copy, Clone, Debug, PartialEq)]
2122
crate enum PlaceBase {
2223
/// Denotes the start of a `Place`.
2324
Local(Local),
@@ -67,7 +68,7 @@ crate enum PlaceBase {
6768
///
6869
/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
6970
/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
70-
#[derive(Clone, Debug)]
71+
#[derive(Clone, Debug, PartialEq)]
7172
crate struct PlaceBuilder<'tcx> {
7273
base: PlaceBase,
7374
projection: Vec<PlaceElem<'tcx>>,
@@ -292,6 +293,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
292293
}
293294
}
294295

296+
/// ROX: Function that will be called when we really do need a place
295297
fn expect_upvars_resolved<'a>(
296298
self,
297299
tcx: TyCtxt<'tcx>,
@@ -319,15 +321,22 @@ impl<'tcx> PlaceBuilder<'tcx> {
319321
self.project(PlaceElem::Field(f, ty))
320322
}
321323

322-
fn deref(self) -> Self {
324+
crate fn deref(self) -> Self {
323325
self.project(PlaceElem::Deref)
324326
}
325327

328+
crate fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Self {
329+
self.project(PlaceElem::Downcast(
330+
Some(adt_def.variants[variant_index].ident.name),
331+
variant_index,
332+
))
333+
}
334+
326335
fn index(self, index: Local) -> Self {
327336
self.project(PlaceElem::Index(index))
328337
}
329338

330-
fn project(mut self, elem: PlaceElem<'tcx>) -> Self {
339+
crate fn project(mut self, elem: PlaceElem<'tcx>) -> Self {
331340
self.projection.push(elem);
332341
self
333342
}
@@ -367,6 +376,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
367376
block.and(place_builder.into_place(self.tcx, self.typeck_results))
368377
}
369378

379+
// ROX: As place builder
370380
/// This is used when constructing a compound `Place`, so that we can avoid creating
371381
/// intermediate `Place` values until we know the full set of projections.
372382
crate fn as_place_builder(
@@ -613,13 +623,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
613623
// The "retagging" transformation (for Stacked Borrows) relies on this.
614624
let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not,));
615625

616-
block = self.bounds_check(
617-
block,
618-
base_place.clone().into_place(self.tcx, self.typeck_results),
619-
idx,
620-
expr_span,
621-
source_info,
622-
);
626+
block = self.bounds_check(block, base_place.clone(), idx, expr_span, source_info);
623627

624628
if is_outermost_index {
625629
self.read_fake_borrows(block, fake_borrow_temps, source_info)
@@ -640,7 +644,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
640644
fn bounds_check(
641645
&mut self,
642646
block: BasicBlock,
643-
slice: Place<'tcx>,
647+
slice: PlaceBuilder<'tcx>,
644648
index: Local,
645649
expr_span: Span,
646650
source_info: SourceInfo,
@@ -652,7 +656,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
652656
let lt = self.temp(bool_ty, expr_span);
653657

654658
// len = len(slice)
655-
self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice));
659+
self.cfg.push_assign(
660+
block,
661+
source_info,
662+
len,
663+
Rvalue::Len(slice.clone().into_place(self.tcx, self.typeck_results)),
664+
);
656665
// lt = idx < len
657666
self.cfg.push_assign(
658667
block,

compiler/rustc_mir_build/src/build/expr/into.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
280280
let field_names: Vec<_> =
281281
(0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect();
282282

283+
// ROX: This is probably here the function record/struct update pattern is done.
283284
let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
284285
let place_builder = unpack!(block = this.as_place_builder(block, base));
285286

compiler/rustc_mir_build/src/build/expr/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
6363
mod as_constant;
6464
mod as_operand;
65-
mod as_place;
65+
pub mod as_place;
6666
mod as_rvalue;
6767
mod as_temp;
6868
mod category;

compiler/rustc_mir_build/src/build/matches/mod.rs

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
// ROX: this folder contains all code for handling patterns, including exhaustiveness checking etc.
2+
// We want to be careful ^^'
3+
14
//! Code related to match expressions. These are sufficiently complex to
25
//! warrant their own module and submodules. :) This main module includes the
36
//! high-level algorithm, the submodules contain the details.
47
//!
58
//! This also includes code for pattern bindings in `let` statements and
69
//! function parameters.
710
11+
use crate::build::expr::as_place::PlaceBuilder;
812
use crate::build::scope::DropKind;
913
use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
1014
use crate::build::{BlockAnd, BlockAndExtension, Builder};
@@ -96,7 +100,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
96100
let scrutinee_place =
97101
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
98102

99-
let mut arm_candidates = self.create_match_candidates(scrutinee_place, &arms);
103+
let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
100104

101105
let match_has_guard = arms.iter().any(|arm| arm.guard.is_some());
102106
let mut candidates =
@@ -121,8 +125,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
121125
mut block: BasicBlock,
122126
scrutinee: &Expr<'_, 'tcx>,
123127
scrutinee_span: Span,
124-
) -> BlockAnd<Place<'tcx>> {
125-
let scrutinee_place = unpack!(block = self.as_place(block, scrutinee));
128+
) -> BlockAnd<PlaceBuilder<'tcx>> {
129+
let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee));
130+
let scrutinee_place =
131+
scrutinee_place_builder.clone().into_place(self.tcx, self.typeck_results);
126132
// Matching on a `scrutinee_place` with an uninhabited type doesn't
127133
// generate any memory reads by itself, and so if the place "expression"
128134
// contains unsafe operations like raw pointer dereferences or union
@@ -142,21 +148,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
142148
let source_info = self.source_info(scrutinee_span);
143149
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
144150

145-
block.and(scrutinee_place)
151+
block.and(scrutinee_place_builder)
146152
}
147153

148154
/// Create the initial `Candidate`s for a `match` expression.
149155
fn create_match_candidates<'pat>(
150156
&mut self,
151-
scrutinee: Place<'tcx>,
157+
scrutinee: PlaceBuilder<'tcx>,
152158
arms: &'pat [Arm<'pat, 'tcx>],
153159
) -> Vec<(&'pat Arm<'pat, 'tcx>, Candidate<'pat, 'tcx>)> {
154160
// Assemble a list of candidates: there is one candidate per pattern,
155161
// which means there may be more than one candidate *per arm*.
156162
arms.iter()
157163
.map(|arm| {
158164
let arm_has_guard = arm.guard.is_some();
159-
let arm_candidate = Candidate::new(scrutinee, &arm.pattern, arm_has_guard);
165+
let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard);
160166
(arm, arm_candidate)
161167
})
162168
.collect()
@@ -222,7 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
222228
fn lower_match_arms(
223229
&mut self,
224230
destination: Place<'tcx>,
225-
scrutinee_place: Place<'tcx>,
231+
scrutinee_place: PlaceBuilder<'tcx>,
226232
scrutinee_span: Span,
227233
arm_candidates: Vec<(&'_ Arm<'_, 'tcx>, Candidate<'_, 'tcx>)>,
228234
outer_source_info: SourceInfo,
@@ -241,7 +247,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
241247
arm.span,
242248
&arm.pattern,
243249
ArmHasGuard(arm.guard.is_some()),
244-
Some((Some(&scrutinee_place), scrutinee_span)),
250+
Some((
251+
Some(
252+
&scrutinee_place.clone().into_place(this.tcx, this.typeck_results),
253+
),
254+
scrutinee_span,
255+
)),
245256
);
246257

247258
let arm_block = this.bind_pattern(
@@ -446,8 +457,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
446457
}
447458

448459
_ => {
449-
let place = unpack!(block = self.as_place(block, initializer));
450-
self.place_into_pattern(block, irrefutable_pat, place, true)
460+
// Converts the destruct pattern into a place
461+
//
462+
// We don't want to convert to a place right away
463+
// because in case of such pattern inside a closure, the projections matching a
464+
// captured place might have not been applied.
465+
// [FIXME] Need to find where this is happening and make the necessary changes there once
466+
// Candidate is modified
467+
//
468+
// We want to use a place builder; Maybe use `as_place_builder`
469+
let place_builder = unpack!(block = self.as_place_builder(block, initializer));
470+
self.place_into_pattern(block, irrefutable_pat, place_builder, true)
451471
}
452472
}
453473
}
@@ -456,9 +476,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
456476
&mut self,
457477
block: BasicBlock,
458478
irrefutable_pat: Pat<'tcx>,
459-
initializer: Place<'tcx>,
479+
initializer: PlaceBuilder<'tcx>,
460480
set_match_place: bool,
461481
) -> BlockAnd<()> {
482+
let place = initializer.clone().into_place(self.tcx, self.typeck_results);
462483
let mut candidate = Candidate::new(initializer, &irrefutable_pat, false);
463484

464485
let fake_borrow_temps =
@@ -478,7 +499,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
478499
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
479500
)))) = self.local_decls[local].local_info
480501
{
481-
*match_place = Some(initializer);
502+
*match_place = Some(place);
482503
} else {
483504
bug!("Let binding to non-user variable.")
484505
}
@@ -717,7 +738,7 @@ struct Candidate<'pat, 'tcx> {
717738
}
718739

719740
impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
720-
fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self {
741+
fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self {
721742
Candidate {
722743
span: pattern.span,
723744
has_guard,
@@ -791,7 +812,7 @@ struct Ascription<'tcx> {
791812
#[derive(Clone, Debug)]
792813
crate struct MatchPair<'pat, 'tcx> {
793814
// this place...
794-
place: Place<'tcx>,
815+
place: PlaceBuilder<'tcx>,
795816

796817
// ... must match this pattern.
797818
pattern: &'pat Pat<'tcx>,
@@ -1198,7 +1219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11981219
&mut otherwise,
11991220
pats,
12001221
or_span,
1201-
place,
1222+
place.clone(),
12021223
fake_borrows,
12031224
);
12041225
});
@@ -1224,12 +1245,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12241245
otherwise: &mut Option<BasicBlock>,
12251246
pats: &'pat [Pat<'tcx>],
12261247
or_span: Span,
1227-
place: Place<'tcx>,
1248+
place: PlaceBuilder<'tcx>,
12281249
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>,
12291250
) {
12301251
debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats);
1231-
let mut or_candidates: Vec<_> =
1232-
pats.iter().map(|pat| Candidate::new(place, pat, candidate.has_guard)).collect();
1252+
let mut or_candidates: Vec<_> = pats
1253+
.iter()
1254+
.map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard))
1255+
.collect();
12331256
let mut or_candidate_refs: Vec<_> = or_candidates.iter_mut().collect();
12341257
let otherwise = if candidate.otherwise_block.is_some() {
12351258
&mut candidate.otherwise_block
@@ -1412,7 +1435,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14121435
// extract the match-pair from the highest priority candidate
14131436
let match_pair = &candidates.first().unwrap().match_pairs[0];
14141437
let mut test = self.test(match_pair);
1415-
let match_place = match_pair.place;
1438+
let match_place = match_pair.place.clone();
14161439

14171440
// most of the time, the test to perform is simply a function
14181441
// of the main candidate; but for a test like SwitchInt, we
@@ -1428,7 +1451,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14281451
}
14291452
TestKind::Switch { adt_def: _, ref mut variants } => {
14301453
for candidate in candidates.iter() {
1431-
if !self.add_variants_to_switch(&match_place, candidate, variants) {
1454+
if !self.add_variants_to_switch(&match_place.clone(), candidate, variants) {
14321455
break;
14331456
}
14341457
}
@@ -1438,7 +1461,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14381461

14391462
// Insert a Shallow borrow of any places that is switched on.
14401463
if let Some(fb) = fake_borrows {
1441-
fb.insert(match_place);
1464+
fb.insert(match_place.clone().into_place(self.tcx, self.typeck_results));
14421465
}
14431466

14441467
// perform the test, branching to one of N blocks. For each of
@@ -1456,7 +1479,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14561479
// encounter a candidate where the test is not relevant; at
14571480
// that point, we stop sorting.
14581481
while let Some(candidate) = candidates.first_mut() {
1459-
if let Some(idx) = self.sort_candidate(&match_place, &test, candidate) {
1482+
if let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) {
14601483
let (candidate, rest) = candidates.split_first_mut().unwrap();
14611484
target_candidates[idx].push(candidate);
14621485
candidates = rest;
@@ -1519,7 +1542,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15191542
target_blocks
15201543
};
15211544

1522-
self.perform_test(block, match_place, &test, make_target_blocks);
1545+
self.perform_test(block, match_place.clone(), &test, make_target_blocks);
15231546
}
15241547

15251548
/// Determine the fake borrows that are needed from a set of places that
@@ -1753,11 +1776,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17531776
}
17541777
Guard::IfLet(pat, scrutinee) => {
17551778
let scrutinee_span = scrutinee.span;
1756-
let scrutinee_place =
1757-
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span));
1758-
let mut guard_candidate = Candidate::new(scrutinee_place, &pat, false);
1779+
let scrutinee_place = unpack!(
1780+
block = self.lower_scrutinee(block, scrutinee.clone(), scrutinee_span)
1781+
);
1782+
let mut guard_candidate = Candidate::new(scrutinee_place.clone(), &pat, false);
17591783
let wildcard = Pat::wildcard_from_ty(pat.ty);
1760-
let mut otherwise_candidate = Candidate::new(scrutinee_place, &wildcard, false);
1784+
let mut otherwise_candidate =
1785+
Candidate::new(scrutinee_place.clone(), &wildcard, false);
17611786
let fake_borrow_temps = self.lower_match_tree(
17621787
block,
17631788
pat.span,
@@ -1769,7 +1794,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17691794
pat.span.to(arm_span.unwrap()),
17701795
pat,
17711796
ArmHasGuard(false),
1772-
Some((Some(&scrutinee_place), scrutinee.span)),
1797+
Some((
1798+
Some(&scrutinee_place.clone().into_place(tcx, self.typeck_results)),
1799+
scrutinee.span,
1800+
)),
17731801
);
17741802
let post_guard_block = self.bind_pattern(
17751803
self.source_info(pat.span),

0 commit comments

Comments
 (0)