@@ -140,7 +140,8 @@ fn check_crate(tcx: ty::ctxt,
140140 let visitor = visit:: mk_vt ( @{
141141 visit_fn: visit_fn,
142142 visit_local: visit_local,
143- visit_expr: visit_expr
143+ visit_expr: visit_expr,
144+ visit_arm: visit_arm,
144145 with * visit:: default_visitor ( )
145146 } ) ;
146147
@@ -191,11 +192,17 @@ enum RelevantDef { RelevantVar(node_id), RelevantSelf }
191192
192193type CaptureInfo = { ln : LiveNode , is_move : bool , rv : RelevantDef } ;
193194
195+ enum LocalKind {
196+ FromMatch ( binding_mode ) ,
197+ FromLetWithInitializer ,
198+ FromLetNoInitializer
199+ }
200+
194201struct LocalInfo {
195202 id : node_id ;
196203 ident: ident;
197204 is_mutbl: bool ;
198- initialized : bool ;
205+ kind : LocalKind ;
199206}
200207
201208enum VarKind {
@@ -209,7 +216,11 @@ enum VarKind {
209216fn relevant_def ( def : def ) -> option < RelevantDef > {
210217 match def {
211218 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+
213224 _ => none
214225 }
215226}
@@ -329,7 +340,16 @@ impl IrMaps {
329340 match vk {
330341 Arg ( id, name, by_move) |
331342 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) , _} ) => {
333353 let v = match self . last_use_map . find ( expr_id) {
334354 some( v) => v,
335355 none => {
@@ -342,7 +362,8 @@ impl IrMaps {
342362 ( * v) . push ( id) ;
343363 }
344364 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) , _} ) => {
346367 debug ! ( "--but it is not owned" ) ;
347368 }
348369 }
@@ -396,7 +417,8 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
396417 let check_vt = visit:: mk_vt ( @{
397418 visit_fn: check_fn,
398419 visit_local: check_local,
399- visit_expr: check_expr
420+ visit_expr: check_expr,
421+ visit_arm: check_arm,
400422 with * visit:: default_visitor ( )
401423 } ) ;
402424 check_vt. visit_block ( body, lsets, check_vt) ;
@@ -419,16 +441,39 @@ fn visit_local(local: @local, &&self: @IrMaps, vt: vt<@IrMaps>) {
419441 debug ! ( "adding local variable %d" , p_id) ;
420442 let name = ast_util:: path_to_ident ( path) ;
421443 self . add_live_node_for_node ( p_id, VarDefNode ( sp) ) ;
444+ let kind = match local. node . init {
445+ some( _) => FromLetWithInitializer ,
446+ none => FromLetNoInitializer
447+ } ;
422448 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
427453 } ) ) ;
428454 }
429455 visit:: visit_local ( local, self , vt) ;
430456}
431457
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+
432477fn visit_expr( expr: @expr, &&self : @IrMaps , vt: vt < @IrMaps > ) {
433478 match expr. node {
434479 // live nodes required for uses or definitions of variables:
@@ -612,6 +657,30 @@ impl Liveness {
612657 }
613658 }
614659
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+
615684 fn idx( ln: LiveNode , var: Variable ) -> uint {
616685 * ln * self . ir. num_vars + * var
617686 }
@@ -894,13 +963,8 @@ impl Liveness {
894963 // once at the func header but otherwise equivalent.
895964
896965 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)
904968 }
905969
906970 fn propagate_through_exprs( exprs: ~[ @expr] ,
@@ -1003,10 +1067,12 @@ impl Liveness {
10031067 self . init_empty( ln, succ) ;
10041068 let mut first_merge = true;
10051069 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) ;
10061074 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) ;
10101076 self . merge_from_succ( ln, arm_succ, first_merge) ;
10111077 first_merge = false;
10121078 } ;
@@ -1409,6 +1475,13 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) {
14091475 visit:: visit_local ( local, self , vt) ;
14101476}
14111477
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+
14121485fn check_expr ( expr : @expr, &&self : @Liveness , vt : vt < @Liveness > ) {
14131486 match expr. node {
14141487 expr_path( _) => {
@@ -1798,10 +1871,12 @@ impl @Liveness {
17981871 } ;
17991872
18001873 if is_assigned {
1874+ // FIXME(#3266)--make liveness warnings lintable
18011875 self . tcx . sess . span_warn (
18021876 sp, fmt ! ( "variable `%s` is assigned to, \
18031877 but never used", name) ) ;
18041878 } else {
1879+ // FIXME(#3266)--make liveness warnings lintable
18051880 self . tcx . sess . span_warn (
18061881 sp, fmt ! ( "unused variable: `%s`" , name) ) ;
18071882 }
@@ -1814,6 +1889,7 @@ impl @Liveness {
18141889 fn warn_about_dead_assign ( sp : span , ln : LiveNode , var : Variable ) {
18151890 if self . live_on_exit ( ln, var) . is_none ( ) {
18161891 for self . should_warn( var) . each |name| {
1892+ // FIXME(#3266)--make liveness warnings lintable
18171893 self . tcx . sess . span_warn (
18181894 sp,
18191895 fmt ! ( "value assigned to `%s` is never read" , name) ) ;
0 commit comments