Skip to content

Commit 8659c5f

Browse files
committed
borrowck nested items in dead code
1 parent f97b3c6 commit 8659c5f

File tree

11 files changed

+140
-64
lines changed

11 files changed

+140
-64
lines changed

compiler/rustc_borrowck/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,14 @@ fn mir_borrowck(
127127
Ok(tcx.arena.alloc(opaque_types))
128128
} else {
129129
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+
130138
let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
131139
do_mir_borrowck(&mut root_cx, def, None).0;
132140
debug_assert!(closure_requirements.is_none());

compiler/rustc_borrowck/src/root_cx.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
6262
self.tainted_by_errors = Some(guar);
6363
}
6464

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> {
6669
debug_assert_eq!(
6770
self.tcx.typeck_root_def_id(def_id.to_def_id()),
6871
self.root_def_id.to_def_id()

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ rustc_queries! {
387387
}
388388
}
389389

390-
query stalled_generators_within(
390+
query nested_bodies_within(
391391
key: LocalDefId
392392
) -> &'tcx ty::List<LocalDefId> {
393393
desc {

compiler/rustc_middle/src/ty/context.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -684,15 +684,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
684684
self.opaque_types_defined_by(defining_anchor)
685685
}
686686

687-
fn opaque_types_and_generators_defined_by(
687+
fn opaque_types_and_coroutines_defined_by(
688688
self,
689689
defining_anchor: Self::LocalDefId,
690690
) -> Self::LocalDefIds {
691691
if self.next_trait_solver_globally() {
692+
let coroutines_defined_by = self
693+
.nested_bodies_within(defining_anchor)
694+
.iter()
695+
.filter(|def_id| self.is_coroutine(def_id.to_def_id()));
692696
self.mk_local_def_ids_from_iter(
693-
self.opaque_types_defined_by(defining_anchor)
694-
.iter()
695-
.chain(self.stalled_generators_within(defining_anchor)),
697+
self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by),
696698
)
697699
} else {
698700
self.opaque_types_defined_by(defining_anchor)

compiler/rustc_ty_utils/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ mod implied_bounds;
2929
mod instance;
3030
mod layout;
3131
mod needs_drop;
32+
mod nested_bodies;
3233
mod opaque_types;
3334
mod representability;
3435
pub mod sig_types;
35-
mod stalled_generators;
3636
mod structural_match;
3737
mod ty;
3838

@@ -51,5 +51,5 @@ pub fn provide(providers: &mut Providers) {
5151
ty::provide(providers);
5252
instance::provide(providers);
5353
structural_match::provide(providers);
54-
stalled_generators::provide(providers);
54+
nested_bodies::provide(providers);
5555
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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>(
8+
tcx: TyCtxt<'tcx>,
9+
item: LocalDefId,
10+
) -> &'tcx ty::List<LocalDefId> {
11+
let body = tcx.hir_body_owned_by(item);
12+
let mut collector =
13+
NestedBodiesVisitor { tcx, root_def_id: item.to_def_id(), nested_bodies: vec![] };
14+
collector.visit_body(body);
15+
tcx.mk_local_def_ids(&collector.nested_bodies)
16+
}
17+
18+
struct NestedBodiesVisitor<'tcx> {
19+
tcx: TyCtxt<'tcx>,
20+
root_def_id: DefId,
21+
nested_bodies: Vec<LocalDefId>,
22+
}
23+
24+
impl<'tcx> Visitor<'tcx> for NestedBodiesVisitor<'tcx> {
25+
fn visit_nested_body(&mut self, id: hir::BodyId) {
26+
let body_def_id = self.tcx.hir_body_owner_def_id(id);
27+
if self.tcx.typeck_root_def_id(body_def_id.to_def_id())
28+
== self.root_def_id
29+
{
30+
self.nested_bodies.push(body_def_id);
31+
let body = self.tcx.hir_body(id);
32+
self.visit_body(body);
33+
}
34+
}
35+
}
36+
37+
pub(super) fn provide(providers: &mut Providers) {
38+
*providers = Providers { nested_bodies_within, ..*providers };
39+
}

compiler/rustc_ty_utils/src/stalled_generators.rs

-54
This file was deleted.

compiler/rustc_type_ir/src/infer_ctxt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl<I: Interner> TypingMode<I> {
100100
pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
101101
TypingMode::Analysis {
102102
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),
104104
}
105105
}
106106

compiler/rustc_type_ir/src/interner.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ pub trait Interner:
341341

342342
fn opaque_types_defined_by(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds;
343343

344-
fn opaque_types_and_generators_defined_by(
344+
fn opaque_types_and_coroutines_defined_by(
345345
self,
346346
defining_anchor: Self::LocalDefId,
347347
) -> Self::LocalDefIds;
+28
Original file line numberDiff line numberDiff 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| -> &'static str { x };
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 numberDiff line numberDiff 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 | |x: &str| -> &'static str { x };
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`.

0 commit comments

Comments
 (0)