Auto merge of #140590 - lcnr:closure-in-dead-code, r=compiler-errors · rust-lang/rust@e9f8103 (original) (raw)
11 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -127,6 +127,14 @@ fn mir_borrowck( | ||
127 | 127 | Ok(tcx.arena.alloc(opaque_types)) |
128 | 128 | } else { |
129 | 129 | let mut root_cx = BorrowCheckRootCtxt::new(tcx, def); |
130 | +// We need to manually borrowck all nested bodies from the HIR as | |
131 | +// we do not generate MIR for dead code. Not doing so causes us to | |
132 | +// never check closures in dead code. | |
133 | +let nested_bodies = tcx.nested_bodies_within(def); | |
134 | +for def_id in nested_bodies { | |
135 | + root_cx.get_or_insert_nested(def_id); | |
136 | +} | |
137 | + | |
130 | 138 | let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } = |
131 | 139 | do_mir_borrowck(&mut root_cx, def, None).0; |
132 | 140 | debug_assert!(closure_requirements.is_none()); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -62,7 +62,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> { | ||
62 | 62 | self.tainted_by_errors = Some(guar); |
63 | 63 | } |
64 | 64 | |
65 | -fn get_or_insert_nested(&mut self, def_id: LocalDefId) -> &PropagatedBorrowCheckResults<'tcx> { | |
65 | +pub(super) fn get_or_insert_nested( | |
66 | +&mut self, | |
67 | +def_id: LocalDefId, | |
68 | +) -> &PropagatedBorrowCheckResults<'tcx> { | |
66 | 69 | debug_assert_eq!( |
67 | 70 | self.tcx.typeck_root_def_id(def_id.to_def_id()), |
68 | 71 | self.root_def_id.to_def_id() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -387,7 +387,7 @@ rustc_queries! { | ||
387 | 387 | } |
388 | 388 | } |
389 | 389 | |
390 | - query stalled_generators_within( | |
390 | + query nested_bodies_within( | |
391 | 391 | key: LocalDefId |
392 | 392 | ) -> &'tcx ty::List<LocalDefId> { |
393 | 393 | desc { |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -691,15 +691,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> { | ||
691 | 691 | self.opaque_types_defined_by(defining_anchor) |
692 | 692 | } |
693 | 693 | |
694 | -fn opaque_types_and_generators_defined_by( | |
694 | +fn opaque_types_and_coroutines_defined_by( | |
695 | 695 | self, |
696 | 696 | defining_anchor: Self::LocalDefId, |
697 | 697 | ) -> Self::LocalDefIds { |
698 | 698 | if self.next_trait_solver_globally() { |
699 | +let coroutines_defined_by = self | |
700 | +.nested_bodies_within(defining_anchor) | |
701 | +.iter() | |
702 | +.filter(|def_id | |
699 | 703 | self.mk_local_def_ids_from_iter( |
700 | -self.opaque_types_defined_by(defining_anchor) | |
701 | -.iter() | |
702 | -.chain(self.stalled_generators_within(defining_anchor)), | |
704 | +self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by), | |
703 | 705 | ) |
704 | 706 | } else { |
705 | 707 | self.opaque_types_defined_by(defining_anchor) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -29,10 +29,10 @@ mod implied_bounds; | ||
29 | 29 | mod instance; |
30 | 30 | mod layout; |
31 | 31 | mod needs_drop; |
32 | +mod nested_bodies; | |
32 | 33 | mod opaque_types; |
33 | 34 | mod representability; |
34 | 35 | pub mod sig_types; |
35 | -mod stalled_generators; | |
36 | 36 | mod structural_match; |
37 | 37 | mod ty; |
38 | 38 | |
@@ -51,5 +51,5 @@ pub fn provide(providers: &mut Providers) { | ||
51 | 51 | ty::provide(providers); |
52 | 52 | instance::provide(providers); |
53 | 53 | structural_match::provide(providers); |
54 | -stalled_generators::provide(providers); | |
54 | +nested_bodies::provide(providers); | |
55 | 55 | } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
1 | +use rustc_hir as hir; | |
2 | +use rustc_hir::def_id::{DefId, LocalDefId}; | |
3 | +use rustc_hir::intravisit::Visitor; | |
4 | +use rustc_middle::query::Providers; | |
5 | +use rustc_middle::ty::{self, TyCtxt}; | |
6 | + | |
7 | +fn nested_bodies_within<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx ty::List<LocalDefId> { | |
8 | +let body = tcx.hir_body_owned_by(item); | |
9 | +let mut collector = | |
10 | +NestedBodiesVisitor { tcx, root_def_id: item.to_def_id(), nested_bodies: vec![] }; | |
11 | + collector.visit_body(body); | |
12 | + tcx.mk_local_def_ids(&collector.nested_bodies) | |
13 | +} | |
14 | + | |
15 | +struct NestedBodiesVisitor<'tcx> { | |
16 | +tcx: TyCtxt<'tcx>, | |
17 | +root_def_id: DefId, | |
18 | +nested_bodies: Vec<LocalDefId>, | |
19 | +} | |
20 | + | |
21 | +impl<'tcx> Visitor<'tcx> for NestedBodiesVisitor<'tcx> { | |
22 | +fn visit_nested_body(&mut self, id: hir::BodyId) { | |
23 | +let body_def_id = self.tcx.hir_body_owner_def_id(id); | |
24 | +if self.tcx.typeck_root_def_id(body_def_id.to_def_id()) == self.root_def_id { | |
25 | +self.nested_bodies.push(body_def_id); | |
26 | +let body = self.tcx.hir_body(id); | |
27 | +self.visit_body(body); | |
28 | +} | |
29 | +} | |
30 | +} | |
31 | + | |
32 | +pub(super) fn provide(providers: &mut Providers) { | |
33 | +*providers = Providers { nested_bodies_within, ..*providers }; | |
34 | +} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -100,7 +100,7 @@ impl<I: Interner> TypingMode { | ||
100 | 100 | pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> { |
101 | 101 | TypingMode::Analysis { |
102 | 102 | defining_opaque_types_and_generators: cx |
103 | -.opaque_types_and_generators_defined_by(body_def_id), | |
103 | +.opaque_types_and_coroutines_defined_by(body_def_id), | |
104 | 104 | } |
105 | 105 | } |
106 | 106 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -341,7 +341,7 @@ pub trait Interner: | ||
341 | 341 | |
342 | 342 | fn opaque_types_defined_by(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds; |
343 | 343 | |
344 | -fn opaque_types_and_generators_defined_by( | |
344 | +fn opaque_types_and_coroutines_defined_by( | |
345 | 345 | self, |
346 | 346 | defining_anchor: Self::LocalDefId, |
347 | 347 | ) -> Self::LocalDefIds; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
1 | +//@ edition: 2024 | |
2 | + | |
3 | +// Regression test for #140583. We want to borrowck nested | |
4 | +// bodies even if they are in dead code. While not necessary for | |
5 | +// soundness, it is desirable to error in such cases. | |
6 | + | |
7 | +fn main() { | |
8 | +return; | |
9 | + |x: &str | |
10 | +//~^ ERROR lifetime may not live long enough | |
11 | + | | |
12 | + | | |
13 | +let temp = 1; | |
14 | +let p: &'static u32 = &temp; | |
15 | +//~^ ERROR `temp` does not live long enough | |
16 | +}; | |
17 | +}; | |
18 | +const { | |
19 | +let temp = 1; | |
20 | +let p: &'static u32 = &temp; | |
21 | +//~^ ERROR `temp` does not live long enough | |
22 | +}; | |
23 | +async { | |
24 | +let temp = 1; | |
25 | +let p: &'static u32 = &temp; | |
26 | +//~^ ERROR `temp` does not live long enough | |
27 | +}; | |
28 | +} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
1 | +error: lifetime may not live long enough | |
2 | + --> $DIR/nested-bodies-in-dead-code.rs:9:33 | |
3 | + | | |
4 | +LL | | |
5 | + | - ^ returning this value requires that `'1` must outlive `'static` | |
6 | + | | |
7 | + | let's call the lifetime of this reference `'1` | |
8 | + | |
9 | +error[E0597]: `temp` does not live long enough | |
10 | + --> $DIR/nested-bodies-in-dead-code.rs:14:35 | |
11 | + | | |
12 | +LL | let temp = 1; | |
13 | + | ---- binding `temp` declared here | |
14 | +LL | let p: &'static u32 = &temp; | |
15 | + | ------------ ^^^^^ borrowed value does not live long enough | |
16 | + | | |
17 | + | type annotation requires that `temp` is borrowed for `'static` | |
18 | +LL | | |
19 | +LL | }; | |
20 | + | - `temp` dropped here while still borrowed | |
21 | + | |
22 | +error[E0597]: `temp` does not live long enough | |
23 | + --> $DIR/nested-bodies-in-dead-code.rs:20:31 | |
24 | + | | |
25 | +LL | let temp = 1; | |
26 | + | ---- binding `temp` declared here | |
27 | +LL | let p: &'static u32 = &temp; | |
28 | + | ------------ ^^^^^ borrowed value does not live long enough | |
29 | + | | |
30 | + | type annotation requires that `temp` is borrowed for `'static` | |
31 | +LL | | |
32 | +LL | }; | |
33 | + | - `temp` dropped here while still borrowed | |
34 | + | |
35 | +error[E0597]: `temp` does not live long enough | |
36 | + --> $DIR/nested-bodies-in-dead-code.rs:25:31 | |
37 | + | | |
38 | +LL | let temp = 1; | |
39 | + | ---- binding `temp` declared here | |
40 | +LL | let p: &'static u32 = &temp; | |
41 | + | ------------ ^^^^^ borrowed value does not live long enough | |
42 | + | | |
43 | + | type annotation requires that `temp` is borrowed for `'static` | |
44 | +LL | | |
45 | +LL | }; | |
46 | + | - `temp` dropped here while still borrowed | |
47 | + | |
48 | +error: aborting due to 4 previous errors | |
49 | + | |
50 | +For more information about this error, try `rustc --explain E0597`. |