about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2020-09-28 00:00:00 +0000
committerTomasz Miąsko <tomasz.miasko@gmail.com>2020-09-29 23:45:31 +0200
commit924e8aaaf21653ffb1775a0ed9be219ee377370b (patch)
tree467b1d08707f469d6e8c3888326189b3cc1ec77f
parent381b445ff5751f9f39ec672b623372dff09c276e (diff)
downloadrust-924e8aaaf21653ffb1775a0ed9be219ee377370b.tar.gz
rust-924e8aaaf21653ffb1775a0ed9be219ee377370b.zip
Liveness analysis for everybody
Perform liveness analysis for every body instead of limiting it to fns.
-rw-r--r--compiler/rustc_passes/src/liveness.rs62
-rw-r--r--src/test/ui/consts/const-block-non-item-statement-3.rs2
-rw-r--r--src/test/ui/consts/const-block-non-item-statement-rpass.rs2
-rw-r--r--src/test/ui/consts/control-flow/drop-pass.rs1
-rw-r--r--src/test/ui/liveness/liveness-consts.rs63
-rw-r--r--src/test/ui/liveness/liveness-consts.stderr68
-rw-r--r--src/test/ui/liveness/liveness-derive.rs2
-rw-r--r--src/test/ui/liveness/liveness-derive.stderr16
8 files changed, 174 insertions, 42 deletions
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index eb2f40a82d1..3446ca11f02 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -90,12 +90,12 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::*;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
-use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
 use rustc_index::vec::IndexVec;
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
@@ -318,49 +318,38 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
         NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
-    fn visit_fn(
-        &mut self,
-        fk: FnKind<'tcx>,
-        decl: &'tcx hir::FnDecl<'tcx>,
-        body_id: hir::BodyId,
-        sp: Span,
-        id: HirId,
-    ) {
-        debug!("visit_fn {:?}", id);
+    fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
+        debug!("visit_body {:?}", body.id());
 
-        // swap in a new set of IR maps for this function body:
-        let def_id = self.tcx.hir().local_def_id(id);
-        let mut fn_maps = IrMaps::new(self.tcx);
+        // swap in a new set of IR maps for this body
+        let mut maps = IrMaps::new(self.tcx);
+        let hir_id = maps.tcx.hir().body_owner(body.id());
+        let def_id = maps.tcx.hir().local_def_id(hir_id);
 
         // Don't run unused pass for #[derive()]
-        if let FnKind::Method(..) = fk {
-            let parent = self.tcx.hir().get_parent_item(id);
-            if let Some(Node::Item(i)) = self.tcx.hir().find(parent) {
-                if i.attrs.iter().any(|a| self.tcx.sess.check_name(a, sym::automatically_derived)) {
+        if let Some(parent) = self.tcx.parent(def_id.to_def_id()) {
+            if let DefKind::Impl = self.tcx.def_kind(parent.expect_local()) {
+                if self.tcx.has_attr(parent, sym::automatically_derived) {
                     return;
                 }
             }
         }
 
-        debug!("creating fn_maps: {:p}", &fn_maps);
-
-        let body = self.tcx.hir().body(body_id);
-
-        if let Some(upvars) = self.tcx.upvars_mentioned(def_id) {
+        if let Some(upvars) = maps.tcx.upvars_mentioned(def_id) {
             for (&var_hir_id, _upvar) in upvars {
-                let var_name = self.tcx.hir().name(var_hir_id);
-                fn_maps.add_variable(Upvar(var_hir_id, var_name));
+                let var_name = maps.tcx.hir().name(var_hir_id);
+                maps.add_variable(Upvar(var_hir_id, var_name));
             }
         }
 
         // gather up the various local variables, significant expressions,
         // and so forth:
-        intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id);
+        intravisit::walk_body(&mut maps, body);
 
         // compute liveness
-        let mut lsets = Liveness::new(&mut fn_maps, def_id);
-        let entry_ln = lsets.compute(&body, sp, id);
-        lsets.log_liveness(entry_ln, id);
+        let mut lsets = Liveness::new(&mut maps, def_id);
+        let entry_ln = lsets.compute(&body, hir_id);
+        lsets.log_liveness(entry_ln, body.id().hir_id);
 
         // check for various error conditions
         lsets.visit_body(body);
@@ -845,8 +834,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         self.rwu_table.assign_unpacked(idx, rwu);
     }
 
-    fn compute(&mut self, body: &hir::Body<'_>, span: Span, id: hir::HirId) -> LiveNode {
-        debug!("compute: using id for body, {:?}", body.value);
+    fn compute(&mut self, body: &hir::Body<'_>, hir_id: HirId) -> LiveNode {
+        debug!("compute: for body {:?}", body.id().hir_id);
 
         // # Liveness of captured variables
         //
@@ -890,7 +879,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             return succ;
         }
 
-        let ty = self.typeck_results.node_type(id);
+        let ty = self.typeck_results.node_type(hir_id);
         match ty.kind() {
             ty::Closure(_def_id, substs) => match substs.as_closure().kind() {
                 ty::ClosureKind::Fn => {}
@@ -899,7 +888,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             },
             ty::Generator(..) => return succ,
             _ => {
-                span_bug!(span, "{} has upvars so it should have a closure type: {:?}", id, ty);
+                span_bug!(
+                    body.value.span,
+                    "{} has upvars so it should have a closure type: {:?}",
+                    hir_id,
+                    ty
+                );
             }
         };
 
diff --git a/src/test/ui/consts/const-block-non-item-statement-3.rs b/src/test/ui/consts/const-block-non-item-statement-3.rs
index 10a4c31f24e..c513946d189 100644
--- a/src/test/ui/consts/const-block-non-item-statement-3.rs
+++ b/src/test/ui/consts/const-block-non-item-statement-3.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![allow(dead_code)]
+#![allow(dead_code, unused)]
 
 type Array = [u32; {  let x = 2; 5 }];
 
diff --git a/src/test/ui/consts/const-block-non-item-statement-rpass.rs b/src/test/ui/consts/const-block-non-item-statement-rpass.rs
index a1b9b586ad0..3e52eb50e75 100644
--- a/src/test/ui/consts/const-block-non-item-statement-rpass.rs
+++ b/src/test/ui/consts/const-block-non-item-statement-rpass.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![allow(dead_code)]
+#![allow(dead_code, unused)]
 
 #[repr(u8)]
 enum Foo {
diff --git a/src/test/ui/consts/control-flow/drop-pass.rs b/src/test/ui/consts/control-flow/drop-pass.rs
index 95f954a59a8..2a6d12768c3 100644
--- a/src/test/ui/consts/control-flow/drop-pass.rs
+++ b/src/test/ui/consts/control-flow/drop-pass.rs
@@ -1,6 +1,7 @@
 // run-pass
 // revisions: stock precise
 
+#![allow(unused)]
 #![cfg_attr(precise, feature(const_precise_live_drops))]
 
 // `x` is always moved into the final value and is not dropped inside the initializer.
diff --git a/src/test/ui/liveness/liveness-consts.rs b/src/test/ui/liveness/liveness-consts.rs
new file mode 100644
index 00000000000..8fe2453ca22
--- /dev/null
+++ b/src/test/ui/liveness/liveness-consts.rs
@@ -0,0 +1,63 @@
+// check-pass
+#![warn(unused)]
+#![allow(unreachable_code)]
+
+pub static A: i32 = {
+    let mut i = 0;
+    let mut a = 0; //~ WARN variable `a` is assigned to, but never used
+    while i < 10 {
+        i += 1;
+        a += 1;
+    }
+    i
+};
+
+pub const B: u32 = {
+    let mut b = 1;
+    b += 1; //~ WARN value assigned to `b` is never read
+    b = 42;
+    b
+};
+
+pub enum E {
+    V1 = {
+        let e = 1; //~ WARN unused variable: `e`
+        1
+    },
+    V2 = {
+        let _f = 10;
+        2
+    }
+}
+
+pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8;  { let z = 18; 100 }] {
+    //~^ WARN unused variable: `s`
+    //~| WARN unused variable: `z`
+    x
+}
+
+pub trait T {
+    const T: usize = {
+        let mut t = 10;
+        t = t + t; //~ WARN value assigned to `t` is never read
+        20
+    };
+}
+
+impl T for String {
+    const T: usize = {
+        let w = 10; //~ WARN unused variable: `w`
+        loop {
+            break;
+            let _ = w;
+        }
+        44
+    };
+}
+
+fn main() {
+    let _ = [(); {
+        let z = 42; //~ WARN unused variable: `z`
+        35
+    }];
+}
diff --git a/src/test/ui/liveness/liveness-consts.stderr b/src/test/ui/liveness/liveness-consts.stderr
new file mode 100644
index 00000000000..fa8a590a819
--- /dev/null
+++ b/src/test/ui/liveness/liveness-consts.stderr
@@ -0,0 +1,68 @@
+warning: variable `a` is assigned to, but never used
+  --> $DIR/liveness-consts.rs:7:9
+   |
+LL |     let mut a = 0;
+   |         ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/liveness-consts.rs:2:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+   = note: consider using `_a` instead
+
+warning: value assigned to `b` is never read
+  --> $DIR/liveness-consts.rs:17:5
+   |
+LL |     b += 1;
+   |     ^
+   |
+note: the lint level is defined here
+  --> $DIR/liveness-consts.rs:2:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `e`
+  --> $DIR/liveness-consts.rs:24:13
+   |
+LL |         let e = 1;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_e`
+
+warning: unused variable: `s`
+  --> $DIR/liveness-consts.rs:33:24
+   |
+LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8;  { let z = 18; 100 }] {
+   |                        ^ help: if this is intentional, prefix it with an underscore: `_s`
+
+warning: unused variable: `z`
+  --> $DIR/liveness-consts.rs:33:55
+   |
+LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8;  { let z = 18; 100 }] {
+   |                                                       ^ help: if this is intentional, prefix it with an underscore: `_z`
+
+warning: unused variable: `z`
+  --> $DIR/liveness-consts.rs:60:13
+   |
+LL |         let z = 42;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_z`
+
+warning: value assigned to `t` is never read
+  --> $DIR/liveness-consts.rs:42:9
+   |
+LL |         t = t + t;
+   |         ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `w`
+  --> $DIR/liveness-consts.rs:49:13
+   |
+LL |         let w = 10;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_w`
+
+warning: 8 warnings emitted
+
diff --git a/src/test/ui/liveness/liveness-derive.rs b/src/test/ui/liveness/liveness-derive.rs
index 66d0b7090ff..1921d0d72bc 100644
--- a/src/test/ui/liveness/liveness-derive.rs
+++ b/src/test/ui/liveness/liveness-derive.rs
@@ -12,7 +12,7 @@ pub trait T: Sized {
 
 impl T for u32 {
     const N: usize = {
-        let a = 0; // FIXME should warn about unused variable
+        let a = 0; //~ WARN unused variable: `a`
         4
     };
 
diff --git a/src/test/ui/liveness/liveness-derive.stderr b/src/test/ui/liveness/liveness-derive.stderr
index d4f45a0a313..c03d9099183 100644
--- a/src/test/ui/liveness/liveness-derive.stderr
+++ b/src/test/ui/liveness/liveness-derive.stderr
@@ -1,8 +1,8 @@
-warning: unused variable: `b`
-  --> $DIR/liveness-derive.rs:20:13
+warning: unused variable: `a`
+  --> $DIR/liveness-derive.rs:15:13
    |
-LL |         let b = 16;
-   |             ^ help: if this is intentional, prefix it with an underscore: `_b`
+LL |         let a = 0;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_a`
    |
 note: the lint level is defined here
   --> $DIR/liveness-derive.rs:6:9
@@ -11,5 +11,11 @@ LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
-warning: 1 warning emitted
+warning: unused variable: `b`
+  --> $DIR/liveness-derive.rs:20:13
+   |
+LL |         let b = 16;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+warning: 2 warnings emitted