Skip to content

Commit 415a8b5

Browse files
Auto merge of #147361 - saethlin:fallible-cycle-detection, r=<try>
Make inliner cycle detection a fallible process
2 parents 227ac7c + 2071fc2 commit 415a8b5

File tree

3 files changed

+18
-14
lines changed

3 files changed

+18
-14
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1294,7 +1294,7 @@ rustc_queries! {
12941294
}
12951295

12961296
/// Return the set of (transitive) callees that may result in a recursive call to `key`.
1297-
query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx UnordSet<LocalDefId> {
1297+
query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx Option<UnordSet<LocalDefId>> {
12981298
fatal_cycle
12991299
arena_cache
13001300
desc { |tcx|

compiler/rustc_mir_transform/src/inline.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,8 +777,11 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>(
777777
{
778778
// If we know for sure that the function we're calling will itself try to
779779
// call us, then we avoid inlining that function.
780-
if inliner.tcx().mir_callgraph_cyclic(caller_def_id.expect_local()).contains(&callee_def_id)
781-
{
780+
let Some(cyclic_callees) = inliner.tcx().mir_callgraph_cyclic(caller_def_id.expect_local())
781+
else {
782+
return Err("call graph cycle detection bailed due to recursion limit");
783+
};
784+
if cyclic_callees.contains(&callee_def_id) {
782785
debug!("query cycle avoidance");
783786
return Err("caller might be reachable from callee");
784787
}

compiler/rustc_mir_transform/src/inline/cycle.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ fn process<'tcx>(
6868
involved: &mut FxHashSet<LocalDefId>,
6969
recursion_limiter: &mut FxHashMap<DefId, usize>,
7070
recursion_limit: Limit,
71-
) -> bool {
71+
) -> Option<bool> {
7272
trace!(%caller);
7373
let mut reaches_root = false;
7474

@@ -127,10 +127,9 @@ fn process<'tcx>(
127127
recursion_limiter,
128128
recursion_limit,
129129
)
130-
})
130+
})?
131131
} else {
132-
// Pessimistically assume that there could be recursion.
133-
true
132+
return None;
134133
};
135134
seen.insert(callee, callee_reaches_root);
136135
callee_reaches_root
@@ -144,14 +143,14 @@ fn process<'tcx>(
144143
}
145144
}
146145

147-
reaches_root
146+
Some(reaches_root)
148147
}
149148

150149
#[instrument(level = "debug", skip(tcx), ret)]
151150
pub(crate) fn mir_callgraph_cyclic<'tcx>(
152151
tcx: TyCtxt<'tcx>,
153152
root: LocalDefId,
154-
) -> UnordSet<LocalDefId> {
153+
) -> Option<UnordSet<LocalDefId>> {
155154
assert!(
156155
!tcx.is_constructor(root.to_def_id()),
157156
"you should not call `mir_callgraph_reachable` on enum/struct constructor functions"
@@ -164,16 +163,16 @@ pub(crate) fn mir_callgraph_cyclic<'tcx>(
164163
// limit, we will hit the limit first and give up on looking for inlining. And in any case,
165164
// the default recursion limits are quite generous for us. If we need to recurse 64 times
166165
// into the call graph, we're probably not going to find any useful MIR inlining.
167-
let recursion_limit = tcx.recursion_limit() / 2;
166+
let recursion_limit = tcx.recursion_limit() / 8;
168167
let mut involved = FxHashSet::default();
169168
let typing_env = ty::TypingEnv::post_analysis(tcx, root);
170169
let root_instance =
171170
ty::Instance::new_raw(root.to_def_id(), ty::GenericArgs::identity_for_item(tcx, root));
172171
if !should_recurse(tcx, root_instance) {
173172
trace!("cannot walk, skipping");
174-
return involved.into();
173+
return Some(involved.into());
175174
}
176-
process(
175+
match process(
177176
tcx,
178177
typing_env,
179178
root_instance,
@@ -182,8 +181,10 @@ pub(crate) fn mir_callgraph_cyclic<'tcx>(
182181
&mut involved,
183182
&mut FxHashMap::default(),
184183
recursion_limit,
185-
);
186-
involved.into()
184+
) {
185+
Some(_) => Some(involved.into()),
186+
_ => None,
187+
}
187188
}
188189

189190
pub(crate) fn mir_inliner_callees<'tcx>(

0 commit comments

Comments
 (0)