Skip to content

Commit 7b65566

Browse files
committed
Rewrite place workflow in rustc_mir/borrow_check
1 parent ec40255 commit 7b65566

File tree

11 files changed

+189
-170
lines changed

11 files changed

+189
-170
lines changed

src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
390390
let borrow_span = borrow_spans.var_or_use();
391391

392392
let proper_span = match root_place.base {
393-
PlaceBase::Local(local) => self.mir.local_decls[local].source_info.span,
393+
PlaceBase::Local(local) if root_place.has_no_projection()
394+
=> self.mir.local_decls[local].source_info.span,
394395
_ => drop_span,
395396
};
396397

@@ -528,15 +529,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
528529
assigned_span: Span,
529530
err_place: &Place<'tcx>,
530531
) {
531-
let (from_arg, local_decl) = if let PlaceBase::Local(local) = err_place.base {
532-
if let LocalKind::Arg = self.mir.local_kind(local) {
533-
(true, Some(&self.mir.local_decls[local]))
534-
} else {
535-
(false, Some(&self.mir.local_decls[local]))
532+
let (mut from_arg, mut local_decl) = (false, None);
533+
534+
if let PlaceBase::Local(local) = err_place.base {
535+
if err_place.has_no_projection() {
536+
if let LocalKind::Arg = self.mir.local_kind(local) {
537+
from_arg = true;
538+
local_decl = Some(&self.mir.local_decls[local]);
539+
} else {
540+
local_decl = Some(&self.mir.local_decls[local]);
541+
}
536542
}
537-
} else {
538-
(false, None)
539-
};
543+
}
540544

541545
// If root local is initialized immediately (everything apart from let
542546
// PATTERN;) then make the error refer to that local, rather than the
@@ -630,7 +634,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
630634
including_downcast: &IncludingDowncast,
631635
) -> Result<(), ()> {
632636
self.append_place_base_to_string(&place.base, buf)?;
633-
if !place.elems.is_empty() {
637+
if !place.has_no_projection() {
634638
for elem in place.elems.iter() {
635639
self.append_place_projection_to_string(place, elem, buf, including_downcast)?;
636640
}
@@ -734,7 +738,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
734738
PlaceBase::Promoted(ref prom) => self.describe_field_from_ty(&prom.1, field),
735739
PlaceBase::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field),
736740
};
737-
if !place.elems.is_empty() {
741+
if !place.has_no_projection() {
738742
for elem in place.elems.iter() {
739743
let proj_str = match elem {
740744
ProjectionElem::Downcast(def, variant_index) => format!(
@@ -986,7 +990,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
986990
match place {
987991
Operand::Copy(place)
988992
| Operand::Move(place)
989-
if PlaceBase::Local(local) == place.base =>
993+
if PlaceBase::Local(local) == place.base &&
994+
place.has_no_projection() =>
990995
{
991996
debug!(
992997
"find_closure_borrow_span: found captured local \

src/librustc_mir/borrow_check/mod.rs

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
2121
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase};
2222
use rustc::mir::{Field, ProjectionElem, Rvalue, Statement, StatementKind};
2323
use rustc::mir::{Terminator, TerminatorKind};
24+
use rustc::mir::tcx::PlaceTy;
2425
use rustc::ty::query::Providers;
2526
use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
2627

@@ -958,9 +959,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
958959
ty::TyClosure(def, substs) => {
959960
if let Place {
960961
base: PlaceBase::Local(local),
961-
elems: _,
962+
elems,
962963
} = drop_place {
963-
if *local == Local::new(1) && !self.mir.upvar_decls.is_empty() {
964+
if *local == Local::new(1)
965+
&& !self.mir.upvar_decls.is_empty()
966+
&& elems.is_empty() {
964967
substs
965968
.upvar_tys(def, self.tcx)
966969
.enumerate()
@@ -973,9 +976,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
973976
ty::TyGenerator(def, substs, _) => {
974977
if let Place {
975978
base: PlaceBase::Local(local),
976-
elems: _,
979+
elems,
977980
} = drop_place {
978-
if *local == Local::new(1) && !self.mir.upvar_decls.is_empty() {
981+
if *local == Local::new(1)
982+
&& !self.mir.upvar_decls.is_empty()
983+
&& elems.is_empty() {
979984
substs
980985
.upvar_tys(def, self.tcx)
981986
.enumerate()
@@ -1405,7 +1410,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
14051410
}
14061411

14071412
if let PlaceBase::Local(local) = place.base {
1408-
self.used_mut.insert(local);
1413+
if place.has_no_projection() {
1414+
self.used_mut.insert(local);
1415+
}
14091416
}
14101417
},
14111418
_ => {}
@@ -1488,7 +1495,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
14881495
// we'll have a memory leak) and assume that all statics have a destructor.
14891496
//
14901497
// FIXME: allow thread-locals to borrow other thread locals?
1491-
let (might_be_alive, will_be_dropped) = if !place.elems.is_empty() {
1498+
let (might_be_alive, will_be_dropped) = if !place.has_no_projection() {
14921499
bug!("root of {:?} is a projection ({:?})?", place, place)
14931500
} else {
14941501
match place.base {
@@ -1769,7 +1776,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
17691776
place: &Place<'tcx>,
17701777
) -> Result<MovePathIndex, NoMovePathFound> {
17711778
let mut prefix = place.clone();
1772-
if !prefix.elems.is_empty() {
1779+
if !prefix.has_no_projection() {
17731780
for (i, _) in prefix.elems.iter().cloned().enumerate().rev() {
17741781
prefix = place.elem_base(self.tcx, i);
17751782
if let Some(mpi) = self.move_path_for_place(&prefix) {
@@ -1802,7 +1809,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
18021809
flow_state: &Flows<'cx, 'gcx, 'tcx>,
18031810
) {
18041811
debug!("check_if_assigned_path_is_moved place: {:?}", place);
1805-
if !place.elems.is_empty() {
1812+
if !place.has_no_projection() {
18061813
let tcx = self.tcx;
18071814
for (i, elem) in place.elems.iter().cloned().enumerate().rev() {
18081815
let base_place = place.elem_base(tcx, i);
@@ -1988,7 +1995,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
19881995
is_local_mutation_allowed,
19891996
} = root_place;
19901997

1991-
if !place.elems.is_empty() {
1998+
if !place.has_no_projection() {
19921999
if let Some(field) = place.is_upvar_field_projection(self.mir, &self.tcx) {
19932000
self.used_mut_upvars.push(field);
19942001
}
@@ -2068,17 +2075,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20682075
is_local_mutation_allowed
20692076
);
20702077

2071-
if !place.elems.is_empty() {
2072-
let mut base_place = place.clone();
2073-
for (i, elem) in place.elems.iter().cloned().enumerate().rev() {
2078+
if !place.has_no_projection() {
2079+
let mut base_ty = place.base.ty(self.mir);
2080+
for elem in place.elems.iter() {
20742081
result = match elem {
20752082
// NOTE(review): deref is really special.
20762083
//
20772084
// All other projections are owned by their base path, so mutable if
20782085
// base path is mutable
20792086
ProjectionElem::Deref => {
2080-
base_place = base_place.elem_base(self.tcx, i);
2081-
let base_ty = base_place.ty(self.mir, self.tcx).to_ty(self.tcx);
2087+
base_ty = PlaceTy::from(base_ty)
2088+
.projection_ty(self.tcx, elem).to_ty(self.tcx);
20822089
match base_ty.sty {
20832090
ty::TyRef(_, _, mutbl) => {
20842091
match mutbl {
@@ -2101,8 +2108,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
21012108
}
21022109
_ => LocalMutationIsAllowed::Yes,
21032110
};
2104-
2105-
continue;
2111+
continue
21062112
}
21072113
}
21082114
}
@@ -2121,9 +2127,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
21212127
}
21222128
}
21232129
// `Box<T>` owns its content, so mutable if its location is mutable
2124-
_ if base_ty.is_box() => {
2125-
continue;
2126-
}
2130+
_ if base_ty.is_box() => { continue; }
21272131
// Deref should only be for reference, pointers or boxes
21282132
_ => bug!("Deref of unexpected type: {:?}", base_ty),
21292133
}
@@ -2221,14 +2225,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
22212225
22222226
let mut deepest = place.clone();
22232227

2224-
if !place.elems.is_empty() {
2228+
if !place.has_no_projection() {
22252229
for (i, elem) in place.elems.iter().cloned().enumerate().rev() {
2226-
deepest = match elem {
2230+
match elem {
22272231
ProjectionElem::Deref
22282232
if place.ty(self.mir, self.tcx).to_ty(self.tcx).is_box() => {
2229-
place.elem_base(self.tcx, i)
2233+
deepest = place.elem_base(self.tcx, i);
22302234
},
2231-
_ => continue,
2235+
_ => {},
22322236
}
22332237
}
22342238
}

src/librustc_mir/borrow_check/move_errors.rs

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -94,38 +94,40 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
9494
if let Some(StatementKind::Assign(
9595
Place {
9696
base: PlaceBase::Local(local),
97-
elems: _,
97+
elems,
9898
},
9999
Rvalue::Use(Operand::Move(move_from)),
100100
)) = self.mir.basic_blocks()[location.block]
101101
.statements
102102
.get(location.statement_index)
103103
.map(|stmt| &stmt.kind)
104104
{
105-
let local_decl = &self.mir.local_decls[*local];
106-
// opt_match_place is the
107-
// match_span is the span of the expression being matched on
108-
// match *x.y { ... } match_place is Some(*x.y)
109-
// ^^^^ match_span is the span of *x.y
110-
//
111-
// opt_match_place is None for let [mut] x = ... statements,
112-
// whether or not the right-hand side is a place expression
113-
if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
114-
opt_match_place: Some((ref opt_match_place, match_span)),
115-
binding_mode: _,
116-
opt_ty_info: _,
117-
}))) = local_decl.is_user_variable
118-
{
119-
self.append_binding_error(
120-
grouped_errors,
121-
kind,
122-
move_from,
123-
*local,
124-
opt_match_place,
125-
match_span,
126-
stmt_source_info.span,
127-
);
128-
return;
105+
if elems.is_empty() {
106+
let local_decl = &self.mir.local_decls[*local];
107+
// opt_match_place is the
108+
// match_span is the span of the expression being matched on
109+
// match *x.y { ... } match_place is Some(*x.y)
110+
// ^^^^ match_span is the span of *x.y
111+
//
112+
// opt_match_place is None for let [mut] x = ... statements,
113+
// whether or not the right-hand side is a place expression
114+
if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
115+
opt_match_place: Some((ref opt_match_place, match_span)),
116+
binding_mode: _,
117+
opt_ty_info: _,
118+
}))) = local_decl.is_user_variable
119+
{
120+
self.append_binding_error(
121+
grouped_errors,
122+
kind,
123+
move_from,
124+
*local,
125+
opt_match_place,
126+
match_span,
127+
stmt_source_info.span,
128+
);
129+
return;
130+
}
129131
}
130132
}
131133
grouped_errors.push(GroupedMoveError::OtherIllegalMove {

src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
9191

9292
if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
9393
if let PlaceBase::Local(borrowed_local) = place.base {
94-
let dropped_local_scope = mir.local_decls[local].visibility_scope;
95-
let borrowed_local_scope =
96-
mir.local_decls[borrowed_local].visibility_scope;
97-
98-
if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
99-
err.note(
100-
"values in a scope are dropped \
101-
in the opposite order they are defined",
102-
);
94+
if place.has_no_projection() {
95+
let dropped_local_scope = mir.local_decls[local].visibility_scope;
96+
let borrowed_local_scope =
97+
mir.local_decls[borrowed_local].visibility_scope;
98+
99+
if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
100+
err.note(
101+
"values in a scope are dropped \
102+
in the opposite order they are defined",
103+
);
104+
}
103105
}
104106
}
105107
}

src/librustc_mir/borrow_check/nll/invalidation.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,15 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> {
328328
// directly accessed in the body of the closure/generator.
329329
ty::TyGenerator(def, substs, ..)
330330
if drop_place.base == PlaceBase::Local(Local::new(1))
331+
&& drop_place.has_no_projection()
331332
&& !self.mir.upvar_decls.is_empty()
332333
=> {
333334
substs.upvar_tys(def, self.infcx.tcx).enumerate()
334335
.for_each(|field| drop_field(self, field));
335336
}
336337
ty::TyClosure(def, substs)
337338
if drop_place.base == PlaceBase::Local(Local::new(1))
339+
&& drop_place.has_no_projection()
338340
&& !self.mir.upvar_decls.is_empty()
339341
=> {
340342
substs.upvar_tys(def, self.infcx.tcx).enumerate()

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
266266
match statement.kind {
267267
StatementKind::Assign(ref place, ref rvalue) => {
268268
debug!("classify_constraint: place={:?} rvalue={:?}", place, rvalue);
269-
if place.base == PlaceBase::Local(mir::RETURN_PLACE) {
269+
if place.base == PlaceBase::Local(mir::RETURN_PLACE) &&
270+
place.has_no_projection() {
270271
ConstraintCategory::Return
271272
} else {
272273
match rvalue {

0 commit comments

Comments
 (0)