From 924e8aaaf21653ffb1775a0ed9be219ee377370b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 28 Sep 2020 00:00:00 +0000 Subject: [PATCH] Liveness analysis for everybody Perform liveness analysis for every body instead of limiting it to fns. --- compiler/rustc_passes/src/liveness.rs | 62 ++++++++--------- .../const-block-non-item-statement-3.rs | 2 +- .../const-block-non-item-statement-rpass.rs | 2 +- src/test/ui/consts/control-flow/drop-pass.rs | 1 + src/test/ui/liveness/liveness-consts.rs | 63 +++++++++++++++++ src/test/ui/liveness/liveness-consts.stderr | 68 +++++++++++++++++++ src/test/ui/liveness/liveness-derive.rs | 2 +- src/test/ui/liveness/liveness-derive.stderr | 16 +++-- 8 files changed, 174 insertions(+), 42 deletions(-) create mode 100644 src/test/ui/liveness/liveness-consts.rs create mode 100644 src/test/ui/liveness/liveness-consts.stderr 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