Skip to content

Commit 71d221f

Browse files
committed
Determine unused mutable variables based on the 'root' place
1 parent e3b372f commit 71d221f

File tree

1 file changed

+111
-86
lines changed
  • src/librustc_mir/borrow_check

1 file changed

+111
-86
lines changed

src/librustc_mir/borrow_check/mod.rs

Lines changed: 111 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
241241
access_place_error_reported: FxHashSet(),
242242
reservation_error_reported: FxHashSet(),
243243
moved_error_reported: FxHashSet(),
244-
nonlexical_regioncx: opt_regioncx,
244+
nonlexical_regioncx: regioncx,
245245
used_mut: FxHashSet(),
246246
used_mut_upvars: SmallVec::new(),
247247
nonlexical_cause_info: None,
@@ -276,7 +276,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
276276

277277
tcx.struct_span_lint_node(
278278
UNUSED_MUT,
279-
vsi[source_info.scope].lint_root,
279+
vsi[local_decl.syntactic_scope].lint_root,
280280
source_info.span,
281281
"variable does not need to be mutable"
282282
)
@@ -1366,7 +1366,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13661366
) {
13671367
debug!("check_if_reassignment_to_immutable_state({:?})", place);
13681368
// determine if this path has a non-mut owner (and thus needs checking).
1369-
if let Ok(()) = self.is_mutable(place, LocalMutationIsAllowed::No) {
1369+
if let Ok(_) = self.is_mutable(place, LocalMutationIsAllowed::No) {
13701370
return;
13711371
}
13721372
debug!(
@@ -1679,27 +1679,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16791679
}
16801680
}
16811681
Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. }))
1682-
| Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => if let Err(place_err) =
1683-
self.is_mutable(place, is_local_mutation_allowed)
1684-
{
1685-
error_reported = true;
1686-
let item_msg = self.get_default_err_msg(place);
1687-
let mut err = self.tcx
1688-
.cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
1689-
err.span_label(span, "cannot borrow as mutable");
1690-
1691-
if place != place_err {
1692-
if let Some(name) = self.describe_place(place_err) {
1693-
err.note(&format!("the value which is causing this path not to be mutable \
1694-
is...: `{}`", name));
1695-
}
1696-
}
1697-
1698-
err.emit();
1699-
},
1700-
Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
1701-
match place {
1702-
Place::Local(local) => {
1682+
| Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => {
1683+
match self.is_mutable(place, is_local_mutation_allowed) {
1684+
Ok(Place::Local(local))
1685+
if is_local_mutation_allowed != LocalMutationIsAllowed::Yes =>
1686+
{
17031687
// If the local may be initialized, and it is now currently being
17041688
// mutated, then it is justified to be annotated with the `mut` keyword,
17051689
// since the mutation may be a possible reassignment.
@@ -1708,77 +1692,118 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
17081692
self.used_mut.insert(*local);
17091693
}
17101694
}
1711-
Place::Projection(ref proj) => {
1695+
Ok(Place::Projection(ref proj)) => {
17121696
if let Some(field) = self.is_upvar_field_projection(&proj.base) {
17131697
self.used_mut_upvars.push(field);
17141698
}
17151699
}
1716-
Place::Static(..) => {}
1717-
}
1718-
if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) {
1719-
error_reported = true;
1720-
let mut err_info = None;
1721-
match *place_err {
1722-
1723-
Place::Projection(box Projection {
1724-
ref base, elem:ProjectionElem::Deref}) => {
1725-
match *base {
1726-
Place::Local(local) => {
1727-
let locations = self.mir.find_assignments(local);
1728-
if locations.len() > 0 {
1729-
let item_msg = if error_reported {
1730-
self.get_secondary_err_msg(base)
1731-
} else {
1732-
self.get_default_err_msg(place)
1733-
};
1734-
let sp = self.mir.source_info(locations[0]).span;
1735-
let mut to_suggest_span = String::new();
1736-
if let Ok(src) =
1737-
self.tcx.sess.codemap().span_to_snippet(sp) {
1738-
to_suggest_span = src[1..].to_string();
1739-
};
1740-
err_info = Some((
1741-
sp,
1742-
"consider changing this to be a \
1743-
mutable reference",
1744-
to_suggest_span,
1745-
item_msg,
1746-
self.get_primary_err_msg(base)));
1747-
}
1748-
},
1749-
_ => {},
1750-
}
1751-
},
1752-
_ => {},
1753-
}
1700+
Ok(Place::Local(_)) |
1701+
Ok(Place::Static(..)) => {}
1702+
Err(place_err) => {
1703+
error_reported = true;
1704+
let item_msg = self.get_default_err_msg(place);
1705+
let mut err = self.tcx
1706+
.cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
1707+
err.span_label(span, "cannot borrow as mutable");
17541708

1755-
if let Some((err_help_span,
1756-
err_help_stmt,
1757-
to_suggest_span,
1758-
item_msg,
1759-
sec_span)) = err_info {
1760-
let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
1761-
err.span_suggestion(err_help_span,
1762-
err_help_stmt,
1763-
format!("&mut {}", to_suggest_span));
1764-
if place != place_err {
1765-
err.span_label(span, sec_span);
1766-
}
1767-
err.emit()
1768-
} else {
1769-
let item_msg_ = self.get_default_err_msg(place);
1770-
let mut err = self.tcx.cannot_assign(span, &item_msg_, Origin::Mir);
1771-
err.span_label(span, "cannot mutate");
17721709
if place != place_err {
17731710
if let Some(name) = self.describe_place(place_err) {
17741711
err.note(&format!("the value which is causing this path not to be \
1775-
mutable is...: `{}`", name));
1712+
mutable is...: `{}`", name));
17761713
}
17771714
}
1715+
17781716
err.emit();
17791717
}
17801718
}
17811719
}
1720+
Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
1721+
match self.is_mutable(place, is_local_mutation_allowed) {
1722+
Ok(Place::Local(local))
1723+
if is_local_mutation_allowed != LocalMutationIsAllowed::Yes =>
1724+
{
1725+
// If the local may be initialized, and it is now currently being
1726+
// mutated, then it is justified to be annotated with the `mut` keyword,
1727+
// since the mutation may be a possible reassignment.
1728+
let mpi = self.move_data.rev_lookup.find_local(*local);
1729+
if flow_state.inits.contains(&mpi) {
1730+
self.used_mut.insert(*local);
1731+
}
1732+
}
1733+
Ok(Place::Projection(ref proj)) => {
1734+
if let Some(field) = self.is_upvar_field_projection(&proj.base) {
1735+
self.used_mut_upvars.push(field);
1736+
}
1737+
}
1738+
Ok(Place::Local(_)) |
1739+
Ok(Place::Static(..)) => {}
1740+
Err(place_err) => {
1741+
error_reported = true;
1742+
1743+
let err_info = if let Place::Projection(
1744+
box Projection {
1745+
ref base,
1746+
elem: ProjectionElem::Deref
1747+
}
1748+
) = *place_err {
1749+
if let Place::Local(local) = *base {
1750+
let locations = self.mir.find_assignments(local);
1751+
if locations.len() > 0 {
1752+
let item_msg = if error_reported {
1753+
self.get_secondary_err_msg(base)
1754+
} else {
1755+
self.get_default_err_msg(place)
1756+
};
1757+
let sp = self.mir.source_info(locations[0]).span;
1758+
let mut to_suggest_span = String::new();
1759+
if let Ok(src) =
1760+
self.tcx.sess.codemap().span_to_snippet(sp) {
1761+
to_suggest_span = src[1..].to_string();
1762+
};
1763+
Some((sp,
1764+
"consider changing this to be a \
1765+
mutable reference",
1766+
to_suggest_span,
1767+
item_msg,
1768+
self.get_primary_err_msg(base)))
1769+
} else {
1770+
None
1771+
}
1772+
} else {
1773+
None
1774+
}
1775+
} else {
1776+
None
1777+
};
1778+
1779+
if let Some((err_help_span,
1780+
err_help_stmt,
1781+
to_suggest_span,
1782+
item_msg,
1783+
sec_span)) = err_info {
1784+
let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
1785+
err.span_suggestion(err_help_span,
1786+
err_help_stmt,
1787+
format!("&mut {}", to_suggest_span));
1788+
if place != place_err {
1789+
err.span_label(span, sec_span);
1790+
}
1791+
err.emit()
1792+
} else {
1793+
let item_msg = self.get_default_err_msg(place);
1794+
let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
1795+
err.span_label(span, "cannot mutate");
1796+
if place != place_err {
1797+
if let Some(name) = self.describe_place(place_err) {
1798+
err.note(&format!("the value which is causing this path not \
1799+
to be mutable is...: `{}`", name));
1800+
}
1801+
}
1802+
err.emit();
1803+
}
1804+
}
1805+
}
1806+
}
17821807
Reservation(WriteKind::Move)
17831808
| Reservation(WriteKind::StorageDeadOrDrop)
17841809
| Reservation(WriteKind::MutableBorrow(BorrowKind::Shared))
@@ -1810,25 +1835,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
18101835
&self,
18111836
place: &'d Place<'tcx>,
18121837
is_local_mutation_allowed: LocalMutationIsAllowed,
1813-
) -> Result<(), &'d Place<'tcx>> {
1838+
) -> Result<&'d Place<'tcx>, &'d Place<'tcx>> {
18141839
match *place {
18151840
Place::Local(local) => {
18161841
let local = &self.mir.local_decls[local];
18171842
match local.mutability {
18181843
Mutability::Not => match is_local_mutation_allowed {
18191844
LocalMutationIsAllowed::Yes | LocalMutationIsAllowed::ExceptUpvars => {
1820-
Ok(())
1845+
Ok(place)
18211846
}
18221847
LocalMutationIsAllowed::No => Err(place),
18231848
},
1824-
Mutability::Mut => Ok(()),
1849+
Mutability::Mut => Ok(place),
18251850
}
18261851
}
18271852
Place::Static(ref static_) =>
18281853
if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
18291854
Err(place)
18301855
} else {
1831-
Ok(())
1856+
Ok(place)
18321857
},
18331858
Place::Projection(ref proj) => {
18341859
match proj.elem {
@@ -1866,7 +1891,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
18661891
hir::MutImmutable => return Err(place),
18671892
// `*mut` raw pointers are always mutable, regardless of context
18681893
// The users have to check by themselve.
1869-
hir::MutMutable => return Ok(()),
1894+
hir::MutMutable => return Ok(place),
18701895
}
18711896
}
18721897
// `Box<T>` owns its content, so mutable if its location is mutable

0 commit comments

Comments
 (0)