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

Commit 685a4c6

Browse files
committed
Use the correct FakeReadCause
1 parent b6cf070 commit 685a4c6

25 files changed

+391
-618
lines changed

compiler/rustc_middle/src/ty/context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ use rustc_hir::{
4747
};
4848
use rustc_index::vec::{Idx, IndexVec};
4949
use rustc_macros::HashStable;
50+
use rustc_middle::mir::FakeReadCause;
5051
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
5152
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
5253
use rustc_session::lint::{Level, Lint};
@@ -430,8 +431,7 @@ pub struct TypeckResults<'tcx> {
430431
/// see `MinCaptureInformationMap` for more details.
431432
pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
432433

433-
/// [FIXME] RFC2229 Change to use HashSet instead of Vec
434-
pub closure_fake_reads: FxHashMap<DefId, Vec<HirPlace<'tcx>>>,
434+
pub closure_fake_reads: FxHashMap<DefId, Vec<(HirPlace<'tcx>, FakeReadCause)>>,
435435

436436
/// Stores the type, expression, span and optional scope span of all types
437437
/// that are live across the yield of this generator (if a generator).

compiler/rustc_mir_build/src/build/block.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,6 @@ 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
10597
StmtKind::Let { remainder_scope, init_scope, pattern, initializer, lint_level } => {
10698
let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
10799
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
@@ -133,8 +125,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
133125
ArmHasGuard(false),
134126
Some((None, initializer_span)),
135127
);
136-
// This is where we get into pattern handling of the let
137-
// statement
138128
this.expr_into_pattern(block, pattern.clone(), init)
139129
})
140130
}

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

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,20 +84,25 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
8484
mir_projections: &[PlaceElem<'tcx>],
8585
) -> Vec<HirProjectionKind> {
8686
let mut hir_projections = Vec::new();
87+
let mut variant = None;
8788

8889
for mir_projection in mir_projections {
8990
let hir_projection = match mir_projection {
9091
ProjectionElem::Deref => HirProjectionKind::Deref,
9192
ProjectionElem::Field(field, _) => {
9293
// We will never encouter this for multivariant enums,
9394
// read the comment for `Downcast`.
94-
HirProjectionKind::Field(field.index() as u32, VariantIdx::new(0))
95+
let variant = variant.unwrap_or(VariantIdx::new(0));
96+
HirProjectionKind::Field(field.index() as u32, variant)
9597
}
96-
ProjectionElem::Downcast(..) => {
97-
// This projections exist only for enums that have
98-
// multiple variants. Since such enums that are captured
99-
// completely, we can stop here.
100-
break;
98+
ProjectionElem::Downcast(.., idx) => {
99+
// This projections exist for enums that have
100+
// single and multiple variants.
101+
// For single variants, enums are not captured completely.
102+
// We keep track of VariantIdx so we can use this information
103+
// if the next ProjectionElem is a Field
104+
variant = Some(*idx);
105+
continue;
101106
}
102107
ProjectionElem::Index(..)
103108
| ProjectionElem::ConstantIndex { .. }
@@ -107,7 +112,7 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
107112
break;
108113
}
109114
};
110-
115+
variant = None;
111116
hir_projections.push(hir_projection);
112117
}
113118

@@ -231,13 +236,12 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
231236
from_builder.projection
232237
)
233238
} else {
234-
// FIXME(project-rfc-2229#24): Handle this case properly
235239
debug!(
236240
"No associated capture found for {:?}[{:#?}]",
237241
var_hir_id, from_builder.projection,
238242
);
239243
}
240-
return Err(upvar_resolved_place_builder);
244+
return Err(from_builder);
241245
};
242246

243247
let closure_ty = typeck_results
@@ -289,11 +293,10 @@ impl<'tcx> PlaceBuilder<'tcx> {
289293
if let PlaceBase::Local(local) = self.base {
290294
Place { local, projection: tcx.intern_place_elems(&self.projection) }
291295
} else {
292-
self.try_upvars_resolved(tcx, typeck_results).into_place(tcx, typeck_results)
296+
self.expect_upvars_resolved(tcx, typeck_results).into_place(tcx, typeck_results)
293297
}
294298
}
295299

296-
/// ROX: Function that will be called when we really do need a place
297300
fn expect_upvars_resolved<'a>(
298301
self,
299302
tcx: TyCtxt<'tcx>,
@@ -302,14 +305,14 @@ impl<'tcx> PlaceBuilder<'tcx> {
302305
to_upvars_resolved_place_builder(self, tcx, typeck_results).unwrap()
303306
}
304307

305-
fn try_upvars_resolved<'a>(
308+
crate fn try_upvars_resolved<'a>(
306309
self,
307310
tcx: TyCtxt<'tcx>,
308311
typeck_results: &'a ty::TypeckResults<'tcx>,
309-
) -> PlaceBuilder<'tcx> {
312+
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
310313
match to_upvars_resolved_place_builder(self, tcx, typeck_results) {
311-
Ok(upvars_resolved) => upvars_resolved,
312-
Err(upvars_unresolved) => upvars_unresolved,
314+
Ok(upvars_resolved) => Ok(upvars_resolved),
315+
Err(upvars_unresolved) => Err(upvars_unresolved),
313316
}
314317
}
315318

@@ -376,7 +379,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
376379
block.and(place_builder.into_place(self.tcx, self.typeck_results))
377380
}
378381

379-
// ROX: As place builder
380382
/// This is used when constructing a compound `Place`, so that we can avoid creating
381383
/// intermediate `Place` values until we know the full set of projections.
382384
crate fn as_place_builder(

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

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
165165

166166
block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields))
167167
}
168-
ExprKind::Closure { closure_id, substs, upvars, movability, fake_reads } => {
168+
ExprKind::Closure {
169+
closure_id,
170+
substs,
171+
upvars,
172+
movability,
173+
fake_reads: opt_fake_reads,
174+
} => {
169175
// see (*) above
170176
let operands: Vec<_> = upvars
171177
.into_iter()
@@ -204,18 +210,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
204210
}
205211
})
206212
.collect();
207-
208-
if let Some(fake_reads) = fake_reads {
209-
for thir_place in fake_reads.into_iter() {
210-
// = this.hir.mirror(thir_place);
211-
let mir_place = unpack!(block = this.as_place(block, thir_place));
212-
// [FIXME] RFC2229 FakeReadCause can be ForLet or ForMatch, need to use the correct one
213-
this.cfg.push_fake_read(
214-
block,
215-
source_info,
216-
FakeReadCause::ForMatchedPlace,
217-
mir_place,
218-
);
213+
if let Some(fake_reads) = opt_fake_reads {
214+
for (thir_place, cause) in fake_reads.into_iter() {
215+
let place_builder =
216+
unpack!(block = this.as_place_builder(block, thir_place));
217+
218+
if let Ok(place_builder_resolved) =
219+
place_builder.clone().try_upvars_resolved(this.tcx, this.typeck_results)
220+
{
221+
let mir_place = place_builder_resolved
222+
.clone()
223+
.into_place(this.tcx, this.typeck_results);
224+
this.cfg.push_fake_read(block, source_info, cause, mir_place);
225+
}
219226
}
220227
}
221228

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ 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.
284283
let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
285284
let place_builder = unpack!(block = this.as_place_builder(block, base));
286285

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

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// ROX: this folder contains all code for handling patterns, including exhaustiveness checking etc.
2-
// We want to be careful ^^'
3-
41
//! Code related to match expressions. These are sufficiently complex to
52
//! warrant their own module and submodules. :) This main module includes the
63
//! high-level algorithm, the submodules contain the details.
@@ -100,7 +97,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10097
let scrutinee_place =
10198
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
10299

103-
let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
100+
let mut arm_candidates =
101+
self.create_match_candidates(scrutinee_place.clone(), &arms.clone());
104102

105103
let match_has_guard = arms.iter().any(|arm| arm.guard.is_some());
106104
let mut candidates =
@@ -127,8 +125,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
127125
scrutinee_span: Span,
128126
) -> BlockAnd<PlaceBuilder<'tcx>> {
129127
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);
132128
// Matching on a `scrutinee_place` with an uninhabited type doesn't
133129
// generate any memory reads by itself, and so if the place "expression"
134130
// contains unsafe operations like raw pointer dereferences or union
@@ -146,7 +142,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
146142
// check safety.
147143
let cause_matched_place = FakeReadCause::ForMatchedPlace;
148144
let source_info = self.source_info(scrutinee_span);
149-
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
145+
146+
if let Ok(scrutinee_builder) =
147+
scrutinee_place_builder.clone().try_upvars_resolved(self.tcx, self.typeck_results)
148+
{
149+
let scrutinee_place =
150+
scrutinee_builder.clone().into_place(self.tcx, self.typeck_results);
151+
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
152+
}
150153

151154
block.and(scrutinee_place_builder)
152155
}
@@ -228,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
228231
fn lower_match_arms(
229232
&mut self,
230233
destination: Place<'tcx>,
231-
scrutinee_place: PlaceBuilder<'tcx>,
234+
scrutinee_place_builder: PlaceBuilder<'tcx>,
232235
scrutinee_span: Span,
233236
arm_candidates: Vec<(&'_ Arm<'_, 'tcx>, Candidate<'_, 'tcx>)>,
234237
outer_source_info: SourceInfo,
@@ -242,17 +245,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
242245
let arm_source_info = self.source_info(arm.span);
243246
let arm_scope = (arm.scope, arm_source_info);
244247
self.in_scope(arm_scope, arm.lint_level, |this| {
248+
let body = arm.body.clone();
249+
let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
250+
let scrutinee_place: Place<'tcx>;
251+
if let Ok(scrutinee_builder) = scrutinee_place_builder
252+
.clone()
253+
.try_upvars_resolved(this.tcx, this.typeck_results)
254+
{
255+
scrutinee_place =
256+
scrutinee_builder.clone().into_place(this.tcx, this.typeck_results);
257+
opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
258+
}
245259
let scope = this.declare_bindings(
246260
None,
247261
arm.span,
248262
&arm.pattern,
249263
ArmHasGuard(arm.guard.is_some()),
250-
Some((
251-
Some(
252-
&scrutinee_place.clone().into_place(this.tcx, this.typeck_results),
253-
),
254-
scrutinee_span,
255-
)),
264+
opt_scrutinee_place,
256265
);
257266

258267
let arm_block = this.bind_pattern(
@@ -457,15 +466,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
457466
}
458467

459468
_ => {
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`
469469
let place_builder = unpack!(block = self.as_place_builder(block, initializer));
470470
self.place_into_pattern(block, irrefutable_pat, place_builder, true)
471471
}
@@ -479,12 +479,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
479479
initializer: PlaceBuilder<'tcx>,
480480
set_match_place: bool,
481481
) -> BlockAnd<()> {
482-
let place = initializer.clone().into_place(self.tcx, self.typeck_results);
483-
let mut candidate = Candidate::new(initializer, &irrefutable_pat, false);
484-
482+
let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false);
485483
let fake_borrow_temps =
486484
self.lower_match_tree(block, irrefutable_pat.span, false, &mut [&mut candidate]);
487-
488485
// For matches and function arguments, the place that is being matched
489486
// can be set when creating the variables. But the place for
490487
// let PATTERN = ... might not even exist until we do the assignment.
@@ -499,7 +496,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
499496
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
500497
)))) = self.local_decls[local].local_info
501498
{
502-
*match_place = Some(place);
499+
if let Ok(match_pair_resolved) =
500+
initializer.clone().try_upvars_resolved(self.tcx, self.typeck_results)
501+
{
502+
let place = match_pair_resolved
503+
.clone()
504+
.into_place(self.tcx, self.typeck_results);
505+
*match_place = Some(place);
506+
}
503507
} else {
504508
bug!("Let binding to non-user variable.")
505509
}
@@ -1461,7 +1465,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14611465

14621466
// Insert a Shallow borrow of any places that is switched on.
14631467
if let Some(fb) = fake_borrows {
1464-
fb.insert(match_place.clone().into_place(self.tcx, self.typeck_results));
1468+
if let Ok(match_place_resolved) =
1469+
match_place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
1470+
{
1471+
let resolved_place =
1472+
match_place_resolved.clone().into_place(self.tcx, self.typeck_results);
1473+
fb.insert(resolved_place);
1474+
}
14651475
}
14661476

14671477
// perform the test, branching to one of N blocks. For each of
@@ -1776,28 +1786,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17761786
}
17771787
Guard::IfLet(pat, scrutinee) => {
17781788
let scrutinee_span = scrutinee.span;
1779-
let scrutinee_place = unpack!(
1789+
let scrutinee_place_builder = unpack!(
17801790
block = self.lower_scrutinee(block, scrutinee.clone(), scrutinee_span)
17811791
);
1782-
let mut guard_candidate = Candidate::new(scrutinee_place.clone(), &pat, false);
1792+
let mut guard_candidate =
1793+
Candidate::new(scrutinee_place_builder.clone(), &pat, false);
17831794
let wildcard = Pat::wildcard_from_ty(pat.ty);
17841795
let mut otherwise_candidate =
1785-
Candidate::new(scrutinee_place.clone(), &wildcard, false);
1796+
Candidate::new(scrutinee_place_builder.clone(), &wildcard, false);
17861797
let fake_borrow_temps = self.lower_match_tree(
17871798
block,
17881799
pat.span,
17891800
false,
17901801
&mut [&mut guard_candidate, &mut otherwise_candidate],
17911802
);
1803+
let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
1804+
let scrutinee_place: Place<'tcx>;
1805+
if let Ok(scrutinee_builder) = scrutinee_place_builder
1806+
.clone()
1807+
.try_upvars_resolved(self.tcx, self.typeck_results)
1808+
{
1809+
scrutinee_place =
1810+
scrutinee_builder.clone().into_place(self.tcx, self.typeck_results);
1811+
opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
1812+
}
17921813
self.declare_bindings(
17931814
None,
17941815
pat.span.to(arm_span.unwrap()),
17951816
pat,
17961817
ArmHasGuard(false),
1797-
Some((
1798-
Some(&scrutinee_place.clone().into_place(tcx, self.typeck_results)),
1799-
scrutinee.span,
1800-
)),
1818+
opt_scrutinee_place,
18011819
);
18021820
let post_guard_block = self.bind_pattern(
18031821
self.source_info(pat.span),

0 commit comments

Comments
 (0)