@@ -17,10 +17,11 @@ use rustc::hir::map::definitions::DefPathData;
17
17
use rustc:: infer:: InferCtxt ;
18
18
use rustc:: ty:: { self , ParamEnv , TyCtxt } ;
19
19
use rustc:: ty:: maps:: Providers ;
20
- use rustc:: mir:: { AssertMessage , BasicBlock , BorrowKind , Location , Place } ;
21
- use rustc:: mir:: { Mir , Mutability , Operand , Projection , ProjectionElem , Rvalue } ;
22
- use rustc:: mir:: { Field , Statement , StatementKind , Terminator , TerminatorKind } ;
23
- use rustc:: mir:: { ClosureRegionRequirements , Local } ;
20
+ use rustc:: lint:: builtin:: UNUSED_MUT ;
21
+ use rustc:: mir:: { AssertMessage , BasicBlock , BorrowKind , ClearCrossCrate , Local } ;
22
+ use rustc:: mir:: { Location , Place , Mir , Mutability , Operand , Projection , ProjectionElem } ;
23
+ use rustc:: mir:: { Rvalue , Field , Statement , StatementKind , Terminator , TerminatorKind } ;
24
+ use rustc:: mir:: ClosureRegionRequirements ;
24
25
25
26
use rustc_data_structures:: control_flow_graph:: dominators:: Dominators ;
26
27
use rustc_data_structures:: fx:: FxHashSet ;
@@ -236,7 +237,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
236
237
access_place_error_reported : FxHashSet ( ) ,
237
238
reservation_error_reported : FxHashSet ( ) ,
238
239
moved_error_reported : FxHashSet ( ) ,
239
- nonlexical_regioncx : regioncx,
240
+ nonlexical_regioncx : opt_regioncx,
241
+ used_mut : FxHashSet ( ) ,
240
242
nonlexical_cause_info : None ,
241
243
borrow_set,
242
244
dominators,
@@ -287,6 +289,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
287
289
/// This field keeps track of errors reported in the checking of moved variables,
288
290
/// so that we don't report report seemingly duplicate errors.
289
291
moved_error_reported : FxHashSet < Place < ' tcx > > ,
292
+ /// This field keeps track of all the local variables that are declared mut and are mutated.
293
+ /// Used for the warning issued by an unused mutable local variable.
294
+ used_mut : FxHashSet < Local > ,
290
295
/// Non-lexical region inference context, if NLL is enabled. This
291
296
/// contains the results from region inference and lets us e.g.
292
297
/// find out which CFG points are contained in each borrow region.
@@ -434,6 +439,22 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
434
439
435
440
self . check_activations ( location, span, flow_state) ;
436
441
442
+ for local in self . mir . mut_vars_iter ( ) . filter ( |local| !self . used_mut . contains ( local) ) {
443
+ if let ClearCrossCrate :: Set ( ref vsi) = self . mir . visibility_scope_info {
444
+ let source_info = self . mir . local_decls [ local] . source_info ;
445
+ let mut_span = self . tcx . sess . codemap ( ) . span_until_non_whitespace ( source_info. span ) ;
446
+
447
+ self . tcx . struct_span_lint_node (
448
+ UNUSED_MUT ,
449
+ vsi[ source_info. scope ] . lint_root ,
450
+ source_info. span ,
451
+ "variable does not need to be mutable"
452
+ )
453
+ . span_suggestion_short ( mut_span, "remove this `mut`" , "" . to_owned ( ) )
454
+ . emit ( ) ;
455
+ }
456
+ }
457
+
437
458
match term. kind {
438
459
TerminatorKind :: SwitchInt {
439
460
ref discr,
@@ -1594,7 +1615,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1594
1615
///
1595
1616
/// Returns true if an error is reported, false otherwise.
1596
1617
fn check_access_permissions (
1597
- & self ,
1618
+ & mut self ,
1598
1619
( place, span) : ( & Place < ' tcx > , Span ) ,
1599
1620
kind : ReadOrWrite ,
1600
1621
is_local_mutation_allowed : LocalMutationIsAllowed ,
@@ -1631,7 +1652,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1631
1652
err. emit ( ) ;
1632
1653
} ,
1633
1654
Reservation ( WriteKind :: Mutate ) | Write ( WriteKind :: Mutate ) => {
1634
-
1655
+ if let Place :: Local ( local) = * place {
1656
+ self . used_mut . insert ( local) ;
1657
+ }
1635
1658
if let Err ( place_err) = self . is_mutable ( place, is_local_mutation_allowed) {
1636
1659
error_reported = true ;
1637
1660
let mut err_info = None ;
0 commit comments