Skip to content

Commit 939cc3e

Browse files
committed
Auto merge of #77281 - tmiasko:liveness-everybody, r=oli-obk
Liveness analysis for everybody Perform liveness analysis for every body instead of limiting it to fns. Fixes #77169.
2 parents 511ed9f + 924e8aa commit 939cc3e

File tree

8 files changed

+174
-42
lines changed

8 files changed

+174
-42
lines changed

compiler/rustc_passes/src/liveness.rs

+28-34
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ use rustc_errors::Applicability;
9090
use rustc_hir as hir;
9191
use rustc_hir::def::*;
9292
use rustc_hir::def_id::LocalDefId;
93-
use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
94-
use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node};
93+
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
94+
use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
9595
use rustc_index::vec::IndexVec;
9696
use rustc_middle::hir::map::Map;
9797
use rustc_middle::ty::query::Providers;
98-
use rustc_middle::ty::{self, TyCtxt};
98+
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
9999
use rustc_session::lint;
100100
use rustc_span::symbol::{kw, sym, Symbol};
101101
use rustc_span::Span;
@@ -318,49 +318,38 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
318318
NestedVisitorMap::OnlyBodies(self.tcx.hir())
319319
}
320320

321-
fn visit_fn(
322-
&mut self,
323-
fk: FnKind<'tcx>,
324-
decl: &'tcx hir::FnDecl<'tcx>,
325-
body_id: hir::BodyId,
326-
sp: Span,
327-
id: HirId,
328-
) {
329-
debug!("visit_fn {:?}", id);
321+
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
322+
debug!("visit_body {:?}", body.id());
330323

331-
// swap in a new set of IR maps for this function body:
332-
let def_id = self.tcx.hir().local_def_id(id);
333-
let mut fn_maps = IrMaps::new(self.tcx);
324+
// swap in a new set of IR maps for this body
325+
let mut maps = IrMaps::new(self.tcx);
326+
let hir_id = maps.tcx.hir().body_owner(body.id());
327+
let def_id = maps.tcx.hir().local_def_id(hir_id);
334328

335329
// Don't run unused pass for #[derive()]
336-
if let FnKind::Method(..) = fk {
337-
let parent = self.tcx.hir().get_parent_item(id);
338-
if let Some(Node::Item(i)) = self.tcx.hir().find(parent) {
339-
if i.attrs.iter().any(|a| self.tcx.sess.check_name(a, sym::automatically_derived)) {
330+
if let Some(parent) = self.tcx.parent(def_id.to_def_id()) {
331+
if let DefKind::Impl = self.tcx.def_kind(parent.expect_local()) {
332+
if self.tcx.has_attr(parent, sym::automatically_derived) {
340333
return;
341334
}
342335
}
343336
}
344337

345-
debug!("creating fn_maps: {:p}", &fn_maps);
346-
347-
let body = self.tcx.hir().body(body_id);
348-
349-
if let Some(upvars) = self.tcx.upvars_mentioned(def_id) {
338+
if let Some(upvars) = maps.tcx.upvars_mentioned(def_id) {
350339
for (&var_hir_id, _upvar) in upvars {
351-
let var_name = self.tcx.hir().name(var_hir_id);
352-
fn_maps.add_variable(Upvar(var_hir_id, var_name));
340+
let var_name = maps.tcx.hir().name(var_hir_id);
341+
maps.add_variable(Upvar(var_hir_id, var_name));
353342
}
354343
}
355344

356345
// gather up the various local variables, significant expressions,
357346
// and so forth:
358-
intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id);
347+
intravisit::walk_body(&mut maps, body);
359348

360349
// compute liveness
361-
let mut lsets = Liveness::new(&mut fn_maps, def_id);
362-
let entry_ln = lsets.compute(&body, sp, id);
363-
lsets.log_liveness(entry_ln, id);
350+
let mut lsets = Liveness::new(&mut maps, def_id);
351+
let entry_ln = lsets.compute(&body, hir_id);
352+
lsets.log_liveness(entry_ln, body.id().hir_id);
364353

365354
// check for various error conditions
366355
lsets.visit_body(body);
@@ -845,8 +834,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
845834
self.rwu_table.assign_unpacked(idx, rwu);
846835
}
847836

848-
fn compute(&mut self, body: &hir::Body<'_>, span: Span, id: hir::HirId) -> LiveNode {
849-
debug!("compute: using id for body, {:?}", body.value);
837+
fn compute(&mut self, body: &hir::Body<'_>, hir_id: HirId) -> LiveNode {
838+
debug!("compute: for body {:?}", body.id().hir_id);
850839

851840
// # Liveness of captured variables
852841
//
@@ -890,7 +879,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
890879
return succ;
891880
}
892881

893-
let ty = self.typeck_results.node_type(id);
882+
let ty = self.typeck_results.node_type(hir_id);
894883
match ty.kind() {
895884
ty::Closure(_def_id, substs) => match substs.as_closure().kind() {
896885
ty::ClosureKind::Fn => {}
@@ -899,7 +888,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
899888
},
900889
ty::Generator(..) => return succ,
901890
_ => {
902-
span_bug!(span, "{} has upvars so it should have a closure type: {:?}", id, ty);
891+
span_bug!(
892+
body.value.span,
893+
"{} has upvars so it should have a closure type: {:?}",
894+
hir_id,
895+
ty
896+
);
903897
}
904898
};
905899

src/test/ui/consts/const-block-non-item-statement-3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-pass
2-
#![allow(dead_code)]
2+
#![allow(dead_code, unused)]
33

44
type Array = [u32; { let x = 2; 5 }];
55

src/test/ui/consts/const-block-non-item-statement-rpass.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-pass
2-
#![allow(dead_code)]
2+
#![allow(dead_code, unused)]
33

44
#[repr(u8)]
55
enum Foo {

src/test/ui/consts/control-flow/drop-pass.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// run-pass
22
// revisions: stock precise
33

4+
#![allow(unused)]
45
#![cfg_attr(precise, feature(const_precise_live_drops))]
56

67
// `x` is always moved into the final value and is not dropped inside the initializer.
+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// check-pass
2+
#![warn(unused)]
3+
#![allow(unreachable_code)]
4+
5+
pub static A: i32 = {
6+
let mut i = 0;
7+
let mut a = 0; //~ WARN variable `a` is assigned to, but never used
8+
while i < 10 {
9+
i += 1;
10+
a += 1;
11+
}
12+
i
13+
};
14+
15+
pub const B: u32 = {
16+
let mut b = 1;
17+
b += 1; //~ WARN value assigned to `b` is never read
18+
b = 42;
19+
b
20+
};
21+
22+
pub enum E {
23+
V1 = {
24+
let e = 1; //~ WARN unused variable: `e`
25+
1
26+
},
27+
V2 = {
28+
let _f = 10;
29+
2
30+
}
31+
}
32+
33+
pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] {
34+
//~^ WARN unused variable: `s`
35+
//~| WARN unused variable: `z`
36+
x
37+
}
38+
39+
pub trait T {
40+
const T: usize = {
41+
let mut t = 10;
42+
t = t + t; //~ WARN value assigned to `t` is never read
43+
20
44+
};
45+
}
46+
47+
impl T for String {
48+
const T: usize = {
49+
let w = 10; //~ WARN unused variable: `w`
50+
loop {
51+
break;
52+
let _ = w;
53+
}
54+
44
55+
};
56+
}
57+
58+
fn main() {
59+
let _ = [(); {
60+
let z = 42; //~ WARN unused variable: `z`
61+
35
62+
}];
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
warning: variable `a` is assigned to, but never used
2+
--> $DIR/liveness-consts.rs:7:9
3+
|
4+
LL | let mut a = 0;
5+
| ^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/liveness-consts.rs:2:9
9+
|
10+
LL | #![warn(unused)]
11+
| ^^^^^^
12+
= note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
13+
= note: consider using `_a` instead
14+
15+
warning: value assigned to `b` is never read
16+
--> $DIR/liveness-consts.rs:17:5
17+
|
18+
LL | b += 1;
19+
| ^
20+
|
21+
note: the lint level is defined here
22+
--> $DIR/liveness-consts.rs:2:9
23+
|
24+
LL | #![warn(unused)]
25+
| ^^^^^^
26+
= note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
27+
= help: maybe it is overwritten before being read?
28+
29+
warning: unused variable: `e`
30+
--> $DIR/liveness-consts.rs:24:13
31+
|
32+
LL | let e = 1;
33+
| ^ help: if this is intentional, prefix it with an underscore: `_e`
34+
35+
warning: unused variable: `s`
36+
--> $DIR/liveness-consts.rs:33:24
37+
|
38+
LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] {
39+
| ^ help: if this is intentional, prefix it with an underscore: `_s`
40+
41+
warning: unused variable: `z`
42+
--> $DIR/liveness-consts.rs:33:55
43+
|
44+
LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] {
45+
| ^ help: if this is intentional, prefix it with an underscore: `_z`
46+
47+
warning: unused variable: `z`
48+
--> $DIR/liveness-consts.rs:60:13
49+
|
50+
LL | let z = 42;
51+
| ^ help: if this is intentional, prefix it with an underscore: `_z`
52+
53+
warning: value assigned to `t` is never read
54+
--> $DIR/liveness-consts.rs:42:9
55+
|
56+
LL | t = t + t;
57+
| ^
58+
|
59+
= help: maybe it is overwritten before being read?
60+
61+
warning: unused variable: `w`
62+
--> $DIR/liveness-consts.rs:49:13
63+
|
64+
LL | let w = 10;
65+
| ^ help: if this is intentional, prefix it with an underscore: `_w`
66+
67+
warning: 8 warnings emitted
68+

src/test/ui/liveness/liveness-derive.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub trait T: Sized {
1212

1313
impl T for u32 {
1414
const N: usize = {
15-
let a = 0; // FIXME should warn about unused variable
15+
let a = 0; //~ WARN unused variable: `a`
1616
4
1717
};
1818

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
warning: unused variable: `b`
2-
--> $DIR/liveness-derive.rs:20:13
1+
warning: unused variable: `a`
2+
--> $DIR/liveness-derive.rs:15:13
33
|
4-
LL | let b = 16;
5-
| ^ help: if this is intentional, prefix it with an underscore: `_b`
4+
LL | let a = 0;
5+
| ^ help: if this is intentional, prefix it with an underscore: `_a`
66
|
77
note: the lint level is defined here
88
--> $DIR/liveness-derive.rs:6:9
@@ -11,5 +11,11 @@ LL | #![warn(unused)]
1111
| ^^^^^^
1212
= note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
1313

14-
warning: 1 warning emitted
14+
warning: unused variable: `b`
15+
--> $DIR/liveness-derive.rs:20:13
16+
|
17+
LL | let b = 16;
18+
| ^ help: if this is intentional, prefix it with an underscore: `_b`
19+
20+
warning: 2 warnings emitted
1521

0 commit comments

Comments
 (0)