Skip to content

Commit afa7408

Browse files
committed
use PlaceRef more consistently instead of loosely coupled local+projection
1 parent 929f66a commit afa7408

File tree

6 files changed

+61
-111
lines changed

6 files changed

+61
-111
lines changed

compiler/rustc_codegen_ssa/src/mir/analyze.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
104104
) {
105105
let cx = self.fx.cx;
106106

107-
if let &[ref proj_base @ .., elem] = place_ref.projection {
107+
if let Some((place_base, elem)) = place_ref.last_projection() {
108108
let mut base_context = if context.is_mutating_use() {
109109
PlaceContext::MutatingUse(MutatingUseContext::Projection)
110110
} else {
@@ -119,8 +119,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
119119
)
120120
);
121121
if is_consume {
122-
let base_ty =
123-
mir::Place::ty_from(place_ref.local, proj_base, self.fx.mir, cx.tcx());
122+
let base_ty = mir::PlaceRef::ty(&place_base, self.fx.mir, cx.tcx());
124123
let base_ty = self.fx.monomorphize(base_ty);
125124

126125
// ZSTs don't require any actual memory access.
@@ -175,11 +174,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
175174
base_context = context;
176175
}
177176

178-
self.process_place(
179-
&mir::PlaceRef { local: place_ref.local, projection: proj_base },
180-
base_context,
181-
location,
182-
);
177+
self.process_place(&place_base, base_context, location);
183178
// HACK(eddyb) this emulates the old `visit_projection_elem`, this
184179
// entire `visit_place`-like `process_place` method should be rewritten,
185180
// now that we have moved to the "slice of projections" representation.

compiler/rustc_codegen_ssa/src/mir/place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
514514

515515
pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> {
516516
let tcx = self.cx.tcx();
517-
let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, self.mir, tcx);
517+
let place_ty = mir::PlaceRef::ty(&place_ref, self.mir, tcx);
518518
self.monomorphize(place_ty.ty)
519519
}
520520
}

compiler/rustc_middle/src/mir/mod.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -1745,18 +1745,14 @@ impl<'tcx> Place<'tcx> {
17451745

17461746
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
17471747
/// a single deref of a local.
1748-
//
1749-
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
1748+
#[inline(always)]
17501749
pub fn local_or_deref_local(&self) -> Option<Local> {
1751-
match self.as_ref() {
1752-
PlaceRef { local, projection: [] }
1753-
| PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local),
1754-
_ => None,
1755-
}
1750+
self.as_ref().local_or_deref_local()
17561751
}
17571752

17581753
/// If this place represents a local variable like `_X` with no
17591754
/// projections, return `Some(_X)`.
1755+
#[inline(always)]
17601756
pub fn as_local(&self) -> Option<Local> {
17611757
self.as_ref().as_local()
17621758
}
@@ -1770,6 +1766,7 @@ impl<'tcx> Place<'tcx> {
17701766
/// As a concrete example, given the place a.b.c, this would yield:
17711767
/// - (a, .b)
17721768
/// - (a.b, .c)
1769+
///
17731770
/// Given a place without projections, the iterator is empty.
17741771
pub fn iter_projections(
17751772
self,
@@ -1790,8 +1787,6 @@ impl From<Local> for Place<'_> {
17901787
impl<'tcx> PlaceRef<'tcx> {
17911788
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
17921789
/// a single deref of a local.
1793-
//
1794-
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
17951790
pub fn local_or_deref_local(&self) -> Option<Local> {
17961791
match *self {
17971792
PlaceRef { local, projection: [] }
@@ -1808,6 +1803,14 @@ impl<'tcx> PlaceRef<'tcx> {
18081803
_ => None,
18091804
}
18101805
}
1806+
1807+
pub fn last_projection(&self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)> {
1808+
if let &[ref proj_base @ .., elem] = self.projection {
1809+
Some((PlaceRef { local: self.local, projection: proj_base }, elem))
1810+
} else {
1811+
None
1812+
}
1813+
}
18111814
}
18121815

18131816
impl Debug for Place<'_> {

compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs

+10-28
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
293293
);
294294
}
295295

296-
let ty =
297-
Place::ty_from(used_place.local, used_place.projection, self.body, self.infcx.tcx)
298-
.ty;
296+
let ty = PlaceRef::ty(&used_place, self.body, self.infcx.tcx).ty;
299297
let needs_note = match ty.kind() {
300298
ty::Closure(id, _) => {
301299
let tables = self.infcx.tcx.typeck(id.expect_local());
@@ -732,8 +730,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
732730
) -> (String, String, String, String) {
733731
// Define a small closure that we can use to check if the type of a place
734732
// is a union.
735-
let union_ty = |place_base, place_projection| {
736-
let ty = Place::ty_from(place_base, place_projection, self.body, self.infcx.tcx).ty;
733+
let union_ty = |place_base| {
734+
let ty = PlaceRef::ty(&place_base, self.body, self.infcx.tcx).ty;
737735
ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
738736
};
739737

@@ -751,15 +749,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
751749
// field access to a union. If we find that, then we will keep the place of the
752750
// union being accessed and the field that was being accessed so we can check the
753751
// second borrowed place for the same union and a access to a different field.
754-
let Place { local, projection } = first_borrowed_place;
755-
756-
let mut cursor = projection.as_ref();
757-
while let [proj_base @ .., elem] = cursor {
758-
cursor = proj_base;
759-
752+
for (place_base, elem) in first_borrowed_place.iter_projections().rev() {
760753
match elem {
761-
ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => {
762-
return Some((PlaceRef { local, projection: proj_base }, field));
754+
ProjectionElem::Field(field, _) if union_ty(place_base).is_some() => {
755+
return Some((place_base, field));
763756
}
764757
_ => {}
765758
}
@@ -769,23 +762,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
769762
.and_then(|(target_base, target_field)| {
770763
// With the place of a union and a field access into it, we traverse the second
771764
// borrowed place and look for a access to a different field of the same union.
772-
let Place { local, ref projection } = second_borrowed_place;
773-
774-
let mut cursor = &projection[..];
775-
while let [proj_base @ .., elem] = cursor {
776-
cursor = proj_base;
777-
765+
for (place_base, elem) in second_borrowed_place.iter_projections().rev() {
778766
if let ProjectionElem::Field(field, _) = elem {
779-
if let Some(union_ty) = union_ty(local, proj_base) {
780-
if field != target_field
781-
&& local == target_base.local
782-
&& proj_base == target_base.projection
783-
{
767+
if let Some(union_ty) = union_ty(place_base) {
768+
if field != target_field && place_base == target_base {
784769
return Some((
785-
self.describe_any_place(PlaceRef {
786-
local,
787-
projection: proj_base,
788-
}),
770+
self.describe_any_place(place_base),
789771
self.describe_any_place(first_borrowed_place.as_ref()),
790772
self.describe_any_place(second_borrowed_place.as_ref()),
791773
union_ty.to_string(),

compiler/rustc_mir/src/borrow_check/mod.rs

+24-50
Original file line numberDiff line numberDiff line change
@@ -1740,20 +1740,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
17401740

17411741
self.check_if_full_path_is_moved(location, desired_action, place_span, flow_state);
17421742

1743-
if let [base_proj @ .., ProjectionElem::Subslice { from, to, from_end: false }] =
1744-
place_span.0.projection
1743+
if let Some((place_base, ProjectionElem::Subslice { from, to, from_end: false })) =
1744+
place_span.0.last_projection()
17451745
{
1746-
let place_ty =
1747-
Place::ty_from(place_span.0.local, base_proj, self.body(), self.infcx.tcx);
1746+
let place_ty = PlaceRef::ty(&place_base, self.body(), self.infcx.tcx);
17481747
if let ty::Array(..) = place_ty.ty.kind() {
1749-
let array_place = PlaceRef { local: place_span.0.local, projection: base_proj };
17501748
self.check_if_subslice_element_is_moved(
17511749
location,
17521750
desired_action,
1753-
(array_place, place_span.1),
1751+
(place_base, place_span.1),
17541752
maybe_uninits,
1755-
*from,
1756-
*to,
1753+
from,
1754+
to,
17571755
);
17581756
return;
17591757
}
@@ -1825,10 +1823,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
18251823
debug!("check_if_assigned_path_is_moved place: {:?}", place);
18261824

18271825
// None case => assigning to `x` does not require `x` be initialized.
1828-
let mut cursor = &*place.projection.as_ref();
1829-
while let [proj_base @ .., elem] = cursor {
1830-
cursor = proj_base;
1831-
1826+
for (place_base, elem) in place.iter_projections().rev() {
18321827
match elem {
18331828
ProjectionElem::Index(_/*operand*/) |
18341829
ProjectionElem::ConstantIndex { .. } |
@@ -1843,10 +1838,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
18431838
ProjectionElem::Deref => {
18441839
self.check_if_full_path_is_moved(
18451840
location, InitializationRequiringAction::Use,
1846-
(PlaceRef {
1847-
local: place.local,
1848-
projection: proj_base,
1849-
}, span), flow_state);
1841+
(place_base, span), flow_state);
18501842
// (base initialized; no need to
18511843
// recur further)
18521844
break;
@@ -1862,15 +1854,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
18621854
// assigning to `P.f` requires `P` itself
18631855
// be already initialized
18641856
let tcx = self.infcx.tcx;
1865-
let base_ty = Place::ty_from(place.local, proj_base, self.body(), tcx).ty;
1857+
let base_ty = PlaceRef::ty(&place_base, self.body(), tcx).ty;
18661858
match base_ty.kind() {
18671859
ty::Adt(def, _) if def.has_dtor(tcx) => {
18681860
self.check_if_path_or_subpath_is_moved(
18691861
location, InitializationRequiringAction::Assignment,
1870-
(PlaceRef {
1871-
local: place.local,
1872-
projection: proj_base,
1873-
}, span), flow_state);
1862+
(place_base, span), flow_state);
18741863

18751864
// (base initialized; no need to
18761865
// recur further)
@@ -1880,10 +1869,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
18801869
// Once `let s; s.x = V; read(s.x);`,
18811870
// is allowed, remove this match arm.
18821871
ty::Adt(..) | ty::Tuple(..) => {
1883-
check_parent_of_field(self, location, PlaceRef {
1884-
local: place.local,
1885-
projection: proj_base,
1886-
}, span, flow_state);
1872+
check_parent_of_field(self, location, place_base, span, flow_state);
18871873

18881874
// rust-lang/rust#21232, #54499, #54986: during period where we reject
18891875
// partial initialization, do not complain about unnecessary `mut` on
@@ -1965,9 +1951,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
19651951
// no move out from an earlier location) then this is an attempt at initialization
19661952
// of the union - we should error in that case.
19671953
let tcx = this.infcx.tcx;
1968-
if let ty::Adt(def, _) =
1969-
Place::ty_from(base.local, base.projection, this.body(), tcx).ty.kind()
1970-
{
1954+
if let ty::Adt(def, _) = PlaceRef::ty(&base, this.body(), tcx).ty.kind() {
19711955
if def.is_union() {
19721956
if this.move_data.path_map[mpi].iter().any(|moi| {
19731957
this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
@@ -2162,9 +2146,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21622146
place: PlaceRef<'tcx>,
21632147
is_local_mutation_allowed: LocalMutationIsAllowed,
21642148
) -> Result<RootPlace<'tcx>, PlaceRef<'tcx>> {
2165-
match place {
2166-
PlaceRef { local, projection: [] } => {
2167-
let local = &self.body.local_decls[local];
2149+
match place.last_projection() {
2150+
None => {
2151+
let local = &self.body.local_decls[place.local];
21682152
match local.mutability {
21692153
Mutability::Not => match is_local_mutation_allowed {
21702154
LocalMutationIsAllowed::Yes => Ok(RootPlace {
@@ -2186,11 +2170,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21862170
}),
21872171
}
21882172
}
2189-
PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
2173+
Some((place_base, elem)) => {
21902174
match elem {
21912175
ProjectionElem::Deref => {
2192-
let base_ty =
2193-
Place::ty_from(place.local, proj_base, self.body(), self.infcx.tcx).ty;
2176+
let base_ty = PlaceRef::ty(&place_base, self.body(), self.infcx.tcx).ty;
21942177

21952178
// Check the kind of deref to decide
21962179
match base_ty.kind() {
@@ -2208,10 +2191,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
22082191
_ => LocalMutationIsAllowed::Yes,
22092192
};
22102193

2211-
self.is_mutable(
2212-
PlaceRef { local: place.local, projection: proj_base },
2213-
mode,
2214-
)
2194+
self.is_mutable(place_base, mode)
22152195
}
22162196
}
22172197
}
@@ -2229,10 +2209,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
22292209
}
22302210
}
22312211
// `Box<T>` owns its content, so mutable if its location is mutable
2232-
_ if base_ty.is_box() => self.is_mutable(
2233-
PlaceRef { local: place.local, projection: proj_base },
2234-
is_local_mutation_allowed,
2235-
),
2212+
_ if base_ty.is_box() => {
2213+
self.is_mutable(place_base, is_local_mutation_allowed)
2214+
}
22362215
// Deref should only be for reference, pointers or boxes
22372216
_ => bug!("Deref of unexpected type: {:?}", base_ty),
22382217
}
@@ -2286,10 +2265,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
22862265
// });
22872266
// }
22882267
// ```
2289-
let _ = self.is_mutable(
2290-
PlaceRef { local: place.local, projection: proj_base },
2291-
is_local_mutation_allowed,
2292-
)?;
2268+
let _ =
2269+
self.is_mutable(place_base, is_local_mutation_allowed)?;
22932270
Ok(RootPlace {
22942271
place_local: place.local,
22952272
place_projection: place.projection,
@@ -2298,10 +2275,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
22982275
}
22992276
}
23002277
} else {
2301-
self.is_mutable(
2302-
PlaceRef { local: place.local, projection: proj_base },
2303-
is_local_mutation_allowed,
2304-
)
2278+
self.is_mutable(place_base, is_local_mutation_allowed)
23052279
}
23062280
}
23072281
}

0 commit comments

Comments
 (0)