@@ -140,7 +140,8 @@ fn check_crate(tcx: ty::ctxt,
140
140
let visitor = visit:: mk_vt ( @{
141
141
visit_fn: visit_fn,
142
142
visit_local: visit_local,
143
- visit_expr: visit_expr
143
+ visit_expr: visit_expr,
144
+ visit_arm: visit_arm,
144
145
with * visit:: default_visitor ( )
145
146
} ) ;
146
147
@@ -191,11 +192,17 @@ enum RelevantDef { RelevantVar(node_id), RelevantSelf }
191
192
192
193
type CaptureInfo = { ln : LiveNode , is_move : bool , rv : RelevantDef } ;
193
194
195
+ enum LocalKind {
196
+ FromMatch ( binding_mode ) ,
197
+ FromLetWithInitializer ,
198
+ FromLetNoInitializer
199
+ }
200
+
194
201
struct LocalInfo {
195
202
id : node_id ;
196
203
ident: ident;
197
204
is_mutbl: bool ;
198
- initialized : bool ;
205
+ kind : LocalKind ;
199
206
}
200
207
201
208
enum VarKind {
@@ -209,7 +216,11 @@ enum VarKind {
209
216
fn relevant_def ( def : def ) -> option < RelevantDef > {
210
217
match def {
211
218
def_self( _) => some ( RelevantSelf ) ,
212
- def_arg( nid, _) | def_local( nid, _) => some ( RelevantVar ( nid) ) ,
219
+
220
+ def_binding( nid, _) |
221
+ def_arg( nid, _) |
222
+ def_local( nid, _) => some ( RelevantVar ( nid) ) ,
223
+
213
224
_ => none
214
225
}
215
226
}
@@ -329,7 +340,16 @@ impl IrMaps {
329
340
match vk {
330
341
Arg ( id, name, by_move) |
331
342
Arg ( id, name, by_copy) |
332
- Local ( LocalInfo { id : id, ident : name, _} ) => {
343
+ Local ( LocalInfo { id : id, ident : name,
344
+ kind : FromLetNoInitializer , _} ) |
345
+ Local ( LocalInfo { id : id, ident : name,
346
+ kind : FromLetWithInitializer , _} ) |
347
+ Local ( LocalInfo { id : id, ident : name,
348
+ kind : FromMatch ( bind_by_value) , _} ) |
349
+ Local ( LocalInfo { id : id, ident : name,
350
+ kind : FromMatch ( bind_by_ref( _) ) , _} ) |
351
+ Local ( LocalInfo { id : id, ident : name,
352
+ kind : FromMatch ( bind_by_move) , _} ) => {
333
353
let v = match self . last_use_map . find ( expr_id) {
334
354
some( v) => v,
335
355
none => {
@@ -342,7 +362,8 @@ impl IrMaps {
342
362
( * v) . push ( id) ;
343
363
}
344
364
Arg ( _, _, by_ref) | Arg ( _, _, by_mutbl_ref) |
345
- Arg ( _, _, by_val) | Self | Field ( _) | ImplicitRet => {
365
+ Arg ( _, _, by_val) | Self | Field ( _) | ImplicitRet |
366
+ Local ( LocalInfo { kind : FromMatch ( bind_by_implicit_ref) , _} ) => {
346
367
debug ! ( "--but it is not owned" ) ;
347
368
}
348
369
}
@@ -396,7 +417,8 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
396
417
let check_vt = visit:: mk_vt ( @{
397
418
visit_fn: check_fn,
398
419
visit_local: check_local,
399
- visit_expr: check_expr
420
+ visit_expr: check_expr,
421
+ visit_arm: check_arm,
400
422
with * visit:: default_visitor ( )
401
423
} ) ;
402
424
check_vt. visit_block ( body, lsets, check_vt) ;
@@ -419,16 +441,39 @@ fn visit_local(local: @local, &&self: @IrMaps, vt: vt<@IrMaps>) {
419
441
debug ! ( "adding local variable %d" , p_id) ;
420
442
let name = ast_util:: path_to_ident ( path) ;
421
443
self . add_live_node_for_node ( p_id, VarDefNode ( sp) ) ;
444
+ let kind = match local. node . init {
445
+ some( _) => FromLetWithInitializer ,
446
+ none => FromLetNoInitializer
447
+ } ;
422
448
self . add_variable ( Local ( LocalInfo {
423
- id : p_id,
424
- ident : name,
425
- is_mutbl : local. node . is_mutbl ,
426
- initialized : local . node . init . is_some ( )
449
+ id : p_id,
450
+ ident : name,
451
+ is_mutbl : local. node . is_mutbl ,
452
+ kind : kind
427
453
} ) ) ;
428
454
}
429
455
visit:: visit_local ( local, self , vt) ;
430
456
}
431
457
458
+ fn visit_arm ( arm : arm , & & self : @IrMaps , vt : vt < @IrMaps > ) {
459
+ let def_map = self . tcx . def_map ;
460
+ for arm. pats. each |pat| {
461
+ do pat_util:: pat_bindings( def_map, pat) |bm, p_id, sp, path| {
462
+ debug ! ( "adding local variable %d from match with bm %?" ,
463
+ p_id, bm) ;
464
+ let name = ast_util:: path_to_ident( path) ;
465
+ self . add_live_node_for_node( p_id, VarDefNode ( sp) ) ;
466
+ self . add_variable( Local ( LocalInfo {
467
+ id : p_id,
468
+ ident : name,
469
+ is_mutbl : false ,
470
+ kind : FromMatch ( bm)
471
+ } ) ) ;
472
+ }
473
+ }
474
+ visit:: visit_arm( arm, self , vt) ;
475
+ }
476
+
432
477
fn visit_expr( expr: @expr, &&self : @IrMaps , vt: vt < @IrMaps > ) {
433
478
match expr. node {
434
479
// live nodes required for uses or definitions of variables:
@@ -612,6 +657,30 @@ impl Liveness {
612
657
}
613
658
}
614
659
660
+ fn arm_pats_bindings( pats: & [ @pat] , f: fn ( LiveNode , Variable , span) ) {
661
+ // only consider the first pattern; any later patterns must have
662
+ // the same bindings, and we also consider the first pattern to be
663
+ // the "authoratative" set of ids
664
+ if !pats. is_empty( ) {
665
+ self. pat_bindings( pats[ 0 ] , f)
666
+ }
667
+ }
668
+
669
+ fn define_bindings_in_pat( pat: @pat, succ: LiveNode ) -> LiveNode {
670
+ self. define_bindings_in_arm_pats( [ pat] , succ)
671
+ }
672
+
673
+ fn define_bindings_in_arm_pats( pats: & [ @pat] ,
674
+ succ: LiveNode ) -> LiveNode {
675
+ let mut succ = succ;
676
+ do self. arm_pats_bindings( pats) |ln, var, _sp| {
677
+ self . init_from_succ( ln, succ) ;
678
+ self . define( ln, var) ;
679
+ succ = ln;
680
+ }
681
+ succ
682
+ }
683
+
615
684
fn idx( ln: LiveNode , var: Variable ) -> uint {
616
685
* ln * self . ir. num_vars + * var
617
686
}
@@ -894,13 +963,8 @@ impl Liveness {
894
963
// once at the func header but otherwise equivalent.
895
964
896
965
let opt_init = local. node. init. map( |i| i. expr ) ;
897
- let mut succ = self . propagate_through_opt_expr ( opt_init, succ) ;
898
- do self. pat_bindings ( local. node . pat ) |ln, var, _sp| {
899
- self . init_from_succ ( ln, succ) ;
900
- self . define ( ln, var) ;
901
- succ = ln;
902
- }
903
- succ
966
+ let succ = self . propagate_through_opt_expr( opt_init, succ) ;
967
+ self . define_bindings_in_pat( local. node. pat, succ)
904
968
}
905
969
906
970
fn propagate_through_exprs( exprs: ~[ @expr] ,
@@ -1003,10 +1067,12 @@ impl Liveness {
1003
1067
self . init_empty( ln, succ) ;
1004
1068
let mut first_merge = true;
1005
1069
for arms. each |arm| {
1070
+ let body_succ =
1071
+ self . propagate_through_block( arm. body, succ) ;
1072
+ let guard_succ =
1073
+ self . propagate_through_opt_expr( arm. guard, body_succ) ;
1006
1074
let arm_succ =
1007
- self . propagate_through_opt_expr (
1008
- arm. guard ,
1009
- self . propagate_through_block ( arm. body , succ) ) ;
1075
+ self . define_bindings_in_arm_pats( arm. pats, guard_succ) ;
1010
1076
self . merge_from_succ( ln, arm_succ, first_merge) ;
1011
1077
first_merge = false;
1012
1078
} ;
@@ -1409,6 +1475,13 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) {
1409
1475
visit:: visit_local ( local, self , vt) ;
1410
1476
}
1411
1477
1478
+ fn check_arm( arm : arm , & & self : @Liveness , vt : vt < @Liveness > ) {
1479
+ do self . arm_pats_bindings ( arm. pats ) |ln, var, sp| {
1480
+ self . warn_about_unused ( sp, ln, var) ;
1481
+ }
1482
+ visit:: visit_arm ( arm, self , vt) ;
1483
+ }
1484
+
1412
1485
fn check_expr ( expr : @expr, &&self : @Liveness , vt : vt < @Liveness > ) {
1413
1486
match expr. node {
1414
1487
expr_path( _) => {
@@ -1798,10 +1871,12 @@ impl @Liveness {
1798
1871
} ;
1799
1872
1800
1873
if is_assigned {
1874
+ // FIXME(#3266)--make liveness warnings lintable
1801
1875
self . tcx . sess . span_warn (
1802
1876
sp, fmt ! ( "variable `%s` is assigned to, \
1803
1877
but never used", name) ) ;
1804
1878
} else {
1879
+ // FIXME(#3266)--make liveness warnings lintable
1805
1880
self . tcx . sess . span_warn (
1806
1881
sp, fmt ! ( "unused variable: `%s`" , name) ) ;
1807
1882
}
@@ -1814,6 +1889,7 @@ impl @Liveness {
1814
1889
fn warn_about_dead_assign ( sp : span , ln : LiveNode , var : Variable ) {
1815
1890
if self . live_on_exit ( ln, var) . is_none ( ) {
1816
1891
for self . should_warn( var) . each |name| {
1892
+ // FIXME(#3266)--make liveness warnings lintable
1817
1893
self . tcx . sess . span_warn (
1818
1894
sp,
1819
1895
fmt ! ( "value assigned to `%s` is never read" , name) ) ;
0 commit comments