Liveness analysis for everybody
Perform liveness analysis for every body instead of limiting it to fns.
This commit is contained in:
parent
381b445ff5
commit
924e8aaaf2
@ -90,12 +90,12 @@ use rustc_errors::Applicability;
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::*;
|
use rustc_hir::def::*;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node};
|
use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
use rustc_middle::ty::query::Providers;
|
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_session::lint;
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -318,49 +318,38 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
|
|||||||
NestedVisitorMap::OnlyBodies(self.tcx.hir())
|
NestedVisitorMap::OnlyBodies(self.tcx.hir())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_fn(
|
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
|
||||||
&mut self,
|
debug!("visit_body {:?}", body.id());
|
||||||
fk: FnKind<'tcx>,
|
|
||||||
decl: &'tcx hir::FnDecl<'tcx>,
|
|
||||||
body_id: hir::BodyId,
|
|
||||||
sp: Span,
|
|
||||||
id: HirId,
|
|
||||||
) {
|
|
||||||
debug!("visit_fn {:?}", id);
|
|
||||||
|
|
||||||
// swap in a new set of IR maps for this function body:
|
// swap in a new set of IR maps for this body
|
||||||
let def_id = self.tcx.hir().local_def_id(id);
|
let mut maps = IrMaps::new(self.tcx);
|
||||||
let mut fn_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()]
|
// Don't run unused pass for #[derive()]
|
||||||
if let FnKind::Method(..) = fk {
|
if let Some(parent) = self.tcx.parent(def_id.to_def_id()) {
|
||||||
let parent = self.tcx.hir().get_parent_item(id);
|
if let DefKind::Impl = self.tcx.def_kind(parent.expect_local()) {
|
||||||
if let Some(Node::Item(i)) = self.tcx.hir().find(parent) {
|
if self.tcx.has_attr(parent, sym::automatically_derived) {
|
||||||
if i.attrs.iter().any(|a| self.tcx.sess.check_name(a, sym::automatically_derived)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("creating fn_maps: {:p}", &fn_maps);
|
if let Some(upvars) = maps.tcx.upvars_mentioned(def_id) {
|
||||||
|
|
||||||
let body = self.tcx.hir().body(body_id);
|
|
||||||
|
|
||||||
if let Some(upvars) = self.tcx.upvars_mentioned(def_id) {
|
|
||||||
for (&var_hir_id, _upvar) in upvars {
|
for (&var_hir_id, _upvar) in upvars {
|
||||||
let var_name = self.tcx.hir().name(var_hir_id);
|
let var_name = maps.tcx.hir().name(var_hir_id);
|
||||||
fn_maps.add_variable(Upvar(var_hir_id, var_name));
|
maps.add_variable(Upvar(var_hir_id, var_name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// gather up the various local variables, significant expressions,
|
// gather up the various local variables, significant expressions,
|
||||||
// and so forth:
|
// and so forth:
|
||||||
intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id);
|
intravisit::walk_body(&mut maps, body);
|
||||||
|
|
||||||
// compute liveness
|
// compute liveness
|
||||||
let mut lsets = Liveness::new(&mut fn_maps, def_id);
|
let mut lsets = Liveness::new(&mut maps, def_id);
|
||||||
let entry_ln = lsets.compute(&body, sp, id);
|
let entry_ln = lsets.compute(&body, hir_id);
|
||||||
lsets.log_liveness(entry_ln, id);
|
lsets.log_liveness(entry_ln, body.id().hir_id);
|
||||||
|
|
||||||
// check for various error conditions
|
// check for various error conditions
|
||||||
lsets.visit_body(body);
|
lsets.visit_body(body);
|
||||||
@ -845,8 +834,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
self.rwu_table.assign_unpacked(idx, rwu);
|
self.rwu_table.assign_unpacked(idx, rwu);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute(&mut self, body: &hir::Body<'_>, span: Span, id: hir::HirId) -> LiveNode {
|
fn compute(&mut self, body: &hir::Body<'_>, hir_id: HirId) -> LiveNode {
|
||||||
debug!("compute: using id for body, {:?}", body.value);
|
debug!("compute: for body {:?}", body.id().hir_id);
|
||||||
|
|
||||||
// # Liveness of captured variables
|
// # Liveness of captured variables
|
||||||
//
|
//
|
||||||
@ -890,7 +879,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
return succ;
|
return succ;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty = self.typeck_results.node_type(id);
|
let ty = self.typeck_results.node_type(hir_id);
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Closure(_def_id, substs) => match substs.as_closure().kind() {
|
ty::Closure(_def_id, substs) => match substs.as_closure().kind() {
|
||||||
ty::ClosureKind::Fn => {}
|
ty::ClosureKind::Fn => {}
|
||||||
@ -899,7 +888,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
},
|
},
|
||||||
ty::Generator(..) => return succ,
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// run-pass
|
// run-pass
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code, unused)]
|
||||||
|
|
||||||
type Array = [u32; { let x = 2; 5 }];
|
type Array = [u32; { let x = 2; 5 }];
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// run-pass
|
// run-pass
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code, unused)]
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum Foo {
|
enum Foo {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// run-pass
|
// run-pass
|
||||||
// revisions: stock precise
|
// revisions: stock precise
|
||||||
|
|
||||||
|
#![allow(unused)]
|
||||||
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
||||||
|
|
||||||
// `x` is always moved into the final value and is not dropped inside the initializer.
|
// `x` is always moved into the final value and is not dropped inside the initializer.
|
||||||
|
63
src/test/ui/liveness/liveness-consts.rs
Normal file
63
src/test/ui/liveness/liveness-consts.rs
Normal file
@ -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
|
||||||
|
}];
|
||||||
|
}
|
68
src/test/ui/liveness/liveness-consts.stderr
Normal file
68
src/test/ui/liveness/liveness-consts.stderr
Normal file
@ -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
|
||||||
|
|
@ -12,7 +12,7 @@ pub trait T: Sized {
|
|||||||
|
|
||||||
impl T for u32 {
|
impl T for u32 {
|
||||||
const N: usize = {
|
const N: usize = {
|
||||||
let a = 0; // FIXME should warn about unused variable
|
let a = 0; //~ WARN unused variable: `a`
|
||||||
4
|
4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
warning: unused variable: `b`
|
warning: unused variable: `a`
|
||||||
--> $DIR/liveness-derive.rs:20:13
|
--> $DIR/liveness-derive.rs:15:13
|
||||||
|
|
|
|
||||||
LL | let b = 16;
|
LL | let a = 0;
|
||||||
| ^ help: if this is intentional, prefix it with an underscore: `_b`
|
| ^ help: if this is intentional, prefix it with an underscore: `_a`
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/liveness-derive.rs:6:9
|
--> $DIR/liveness-derive.rs:6:9
|
||||||
@ -11,5 +11,11 @@ LL | #![warn(unused)]
|
|||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
= note: `#[warn(unused_variables)]` implied by `#[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
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user