mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
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::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
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, unused)]
|
||||
|
||||
type Array = [u32; { let x = 2; 5 }];
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, unused)]
|
||||
|
||||
#[repr(u8)]
|
||||
enum Foo {
|
||||
|
@ -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.
|
||||
|
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 {
|
||||
const N: usize = {
|
||||
let a = 0; // FIXME should warn about unused variable
|
||||
let a = 0; //~ WARN unused variable: `a`
|
||||
4
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user