Skip to content

Commit 46f81fc

Browse files
committed
Avoid cloning Place in report_use_of_moved_or_uninitialized and friends
1 parent ec65db0 commit 46f81fc

File tree

17 files changed

+253
-231
lines changed

17 files changed

+253
-231
lines changed

src/librustc/mir/mod.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1826,7 +1826,7 @@ newtype_index! {
18261826
}
18271827
}
18281828

1829-
#[derive(Debug)]
1829+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
18301830
pub struct PlaceRef<'a, 'tcx> {
18311831
pub base: &'a PlaceBase<'tcx>,
18321832
pub projection: &'a Option<Box<Projection<'tcx>>>,
@@ -1961,6 +1961,27 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
19611961
) -> R {
19621962
Place::iterate_over(self.base, self.projection, op)
19631963
}
1964+
1965+
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
1966+
/// a single deref of a local.
1967+
//
1968+
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
1969+
pub fn local_or_deref_local(&self) -> Option<Local> {
1970+
match self {
1971+
PlaceRef {
1972+
base: PlaceBase::Local(local),
1973+
projection: None,
1974+
} |
1975+
PlaceRef {
1976+
base: PlaceBase::Local(local),
1977+
projection: Some(box Projection {
1978+
base: None,
1979+
elem: ProjectionElem::Deref,
1980+
}),
1981+
} => Some(*local),
1982+
_ => None,
1983+
}
1984+
}
19641985
}
19651986

19661987
/// A linked list of projections running up the stack; begins with the

src/librustc_mir/borrow_check/conflict_errors.rs

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc::hir;
22
use rustc::hir::def_id::DefId;
33
use rustc::mir::{
44
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local,
5-
LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, Projection,
5+
LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, Projection, PlaceRef,
66
ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
77
};
88
use rustc::ty::{self, Ty};
@@ -48,7 +48,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
4848
&mut self,
4949
location: Location,
5050
desired_action: InitializationRequiringAction,
51-
(moved_place, used_place, span): (&Place<'tcx>, &Place<'tcx>, Span),
51+
(moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'cx, 'tcx>, Span),
5252
mpi: MovePathIndex,
5353
) {
5454
debug!(
@@ -73,25 +73,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
7373

7474
if move_out_indices.is_empty() {
7575
let root_place = self
76-
.prefixes(&used_place.base, &used_place.projection, PrefixSet::All)
76+
.prefixes(used_place, PrefixSet::All)
7777
.last()
7878
.unwrap();
7979

80-
if self.uninitialized_error_reported.contains(&Place {
81-
base: root_place.0.clone(),
82-
projection: root_place.1.clone(),
83-
}) {
80+
if self.uninitialized_error_reported.contains(&root_place) {
8481
debug!(
8582
"report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
8683
root_place
8784
);
8885
return;
8986
}
9087

91-
self.uninitialized_error_reported.insert(Place {
92-
base: root_place.0.clone(),
93-
projection: root_place.1.clone(),
94-
});
88+
self.uninitialized_error_reported.insert(root_place);
9589

9690
let item_msg = match self.describe_place_with_options(used_place,
9791
IncludingDowncast(true)) {
@@ -114,8 +108,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
114108
err.buffer(&mut self.errors_buffer);
115109
} else {
116110
if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) {
117-
if self.prefixes(&reported_place.base, &reported_place.projection, PrefixSet::All)
118-
.any(|p| *p.0 == used_place.base && *p.1 == used_place.projection)
111+
if self.prefixes(*reported_place, PrefixSet::All)
112+
.any(|p| p == used_place)
119113
{
120114
debug!(
121115
"report_use_of_moved_or_uninitialized place: error suppressed \
@@ -132,7 +126,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
132126
span,
133127
desired_action.as_noun(),
134128
msg,
135-
self.describe_place_with_options(&moved_place, IncludingDowncast(true)),
129+
self.describe_place_with_options(moved_place, IncludingDowncast(true)),
136130
);
137131

138132
self.add_moved_or_invoked_closure_note(
@@ -145,13 +139,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
145139
let is_partial_move = move_site_vec.iter().any(|move_site| {
146140
let move_out = self.move_data.moves[(*move_site).moi];
147141
let moved_place = &self.move_data.move_paths[move_out.path].place;
148-
used_place != moved_place && used_place.is_prefix_of(moved_place)
142+
used_place != moved_place.as_place_ref()
143+
&& used_place.is_prefix_of(moved_place.as_place_ref())
149144
});
150145
for move_site in &move_site_vec {
151146
let move_out = self.move_data.moves[(*move_site).moi];
152147
let moved_place = &self.move_data.move_paths[move_out.path].place;
153148

154-
let move_spans = self.move_spans(moved_place, move_out.source);
149+
let move_spans = self.move_spans(moved_place.as_place_ref(), move_out.source);
155150
let move_span = move_spans.args_or_use();
156151

157152
let move_msg = if move_spans.for_closure() {
@@ -209,7 +204,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
209204
);
210205
}
211206

212-
let ty = used_place.ty(self.body, self.infcx.tcx).ty;
207+
let ty =
208+
Place::ty_from(used_place.base, used_place.projection, self.body, self.infcx.tcx)
209+
.ty;
213210
let needs_note = match ty.sty {
214211
ty::Closure(id, _) => {
215212
let tables = self.infcx.tcx.typeck_tables_of(id);
@@ -225,7 +222,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
225222
let place = &self.move_data.move_paths[mpi].place;
226223

227224
let ty = place.ty(self.body, self.infcx.tcx).ty;
228-
let opt_name = self.describe_place_with_options(place, IncludingDowncast(true));
225+
let opt_name =
226+
self.describe_place_with_options(place.as_place_ref(), IncludingDowncast(true));
229227
let note_msg = match opt_name {
230228
Some(ref name) => format!("`{}`", name),
231229
None => "value".to_owned(),
@@ -259,7 +257,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
259257
}
260258

261259
if let Some((_, mut old_err)) = self.move_error_reported
262-
.insert(move_out_indices, (used_place.clone(), err))
260+
.insert(move_out_indices, (used_place, err))
263261
{
264262
// Cancel the old error so it doesn't ICE.
265263
old_err.cancel();
@@ -289,7 +287,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
289287
let borrow_spans = self.retrieve_borrow_spans(borrow);
290288
let borrow_span = borrow_spans.args_or_use();
291289

292-
let move_spans = self.move_spans(place, location);
290+
let move_spans = self.move_spans(place.as_place_ref(), location);
293291
let span = move_spans.args_or_use();
294292

295293
let mut err = self.cannot_move_when_borrowed(
@@ -328,7 +326,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
328326

329327
// Conflicting borrows are reported separately, so only check for move
330328
// captures.
331-
let use_spans = self.move_spans(place, location);
329+
let use_spans = self.move_spans(place.as_place_ref(), location);
332330
let span = use_spans.var_or_use();
333331

334332
let mut err = self.cannot_use_when_mutably_borrowed(
@@ -698,25 +696,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
698696
);
699697

700698
let drop_span = place_span.1;
701-
let root_place = self.prefixes(&borrow.borrowed_place.base,
702-
&borrow.borrowed_place.projection,
703-
PrefixSet::All)
699+
let root_place = self.prefixes(borrow.borrowed_place.as_place_ref(), PrefixSet::All)
704700
.last()
705701
.unwrap();
706702

707703
let borrow_spans = self.retrieve_borrow_spans(borrow);
708704
let borrow_span = borrow_spans.var_or_use();
709705

710-
assert!(root_place.1.is_none());
711-
let proper_span = match root_place.0 {
706+
assert!(root_place.projection.is_none());
707+
let proper_span = match root_place.base {
712708
PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span,
713709
_ => drop_span,
714710
};
715711

716712
if self.access_place_error_reported
717713
.contains(&(Place {
718-
base: root_place.0.clone(),
719-
projection: root_place.1.clone(),
714+
base: root_place.base.clone(),
715+
projection: root_place.projection.clone(),
720716
}, borrow_span))
721717
{
722718
debug!(
@@ -728,8 +724,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
728724

729725
self.access_place_error_reported
730726
.insert((Place {
731-
base: root_place.0.clone(),
732-
projection: root_place.1.clone(),
727+
base: root_place.base.clone(),
728+
projection: root_place.projection.clone(),
733729
}, borrow_span));
734730

735731
if let StorageDeadOrDrop::Destructor(dropped_ty) =
@@ -739,7 +735,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
739735
// we're not in the uninteresting case where `B` is a
740736
// prefix of `D`), then report this as a more interesting
741737
// destructor conflict.
742-
if !borrow.borrowed_place.is_prefix_of(place_span.0) {
738+
if !borrow.borrowed_place.as_place_ref().is_prefix_of(place_span.0.as_place_ref()) {
743739
self.report_borrow_conflicts_with_destructor(
744740
location, borrow, place_span, kind, dropped_ty,
745741
);
@@ -753,10 +749,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
753749
let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place);
754750

755751
let err = match (place_desc, explanation) {
756-
(Some(_), _) if self.is_place_thread_local(&Place {
757-
base: root_place.0.clone(),
758-
projection: root_place.1.clone(),
759-
}) => {
752+
(Some(_), _) if self.is_place_thread_local(root_place) => {
760753
self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span)
761754
}
762755
// If the outlives constraint comes from inside the closure,
@@ -1133,12 +1126,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11331126
format!("`{}` is borrowed here", place_desc),
11341127
)
11351128
} else {
1136-
let root_place = self.prefixes(&borrow.borrowed_place.base,
1137-
&borrow.borrowed_place.projection,
1129+
let root_place = self.prefixes(borrow.borrowed_place.as_place_ref(),
11381130
PrefixSet::All)
11391131
.last()
11401132
.unwrap();
1141-
let local = if let (PlaceBase::Local(local), None) = root_place {
1133+
let local = if let PlaceRef {
1134+
base: PlaceBase::Local(local),
1135+
projection: None,
1136+
} = root_place {
11421137
local
11431138
} else {
11441139
bug!("try_report_cannot_return_reference_to_local: not a local")

0 commit comments

Comments
 (0)