Skip to content

Commit e798480

Browse files
Auto merge of #143638 - lcnr:overflow-bail, r=<try>
try evaluate nested goals with reduced depth first
2 parents 3c30dbb + 93078e8 commit e798480

File tree

5 files changed

+82
-12
lines changed

5 files changed

+82
-12
lines changed

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_type_ir::{
1313
self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _,
1414
TypeVisitor, TypingMode, Upcast as _, elaborate,
1515
};
16-
use tracing::{debug, instrument};
16+
use tracing::{debug, instrument, debug_span};
1717

1818
use super::trait_goals::TraitGoalProvenVia;
1919
use super::{has_only_region_constraints, inspect};
@@ -958,13 +958,19 @@ where
958958
// If the trait goal has been proven by using the environment, we want to treat
959959
// aliases as rigid if there are no applicable projection bounds in the environment.
960960
if considered_candidates.is_empty() {
961+
let _span = debug_span!("inject_normalize_to_rigid_candidate");
962+
let _span = _span.enter();
961963
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
962964
considered_candidates.push(response);
963965
}
964966
}
965967

966968
if let Some(response) = self.try_merge_responses(&considered_candidates) {
967-
Ok(response)
969+
if response.value.certainty == Certainty::Yes && response.value.external_constraints.normalization_nested_goals.is_empty() {
970+
Ok(response)
971+
} else {
972+
self.flounder(&considered_candidates)
973+
}
968974
} else {
969975
self.flounder(&considered_candidates)
970976
}

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,19 @@ where
335335
(result, proof_tree)
336336
}
337337

338+
pub(super) fn with_capped_depth<R>(
339+
&mut self,
340+
max_depth: usize,
341+
f: impl FnOnce(&mut Self) -> R,
342+
) -> R {
343+
let info = self.search_graph.with_capped_depth_start(max_depth);
344+
let r = f(self);
345+
if let Some(info) = info {
346+
self.search_graph.with_capped_depth_end(info);
347+
}
348+
r
349+
}
350+
338351
/// Creates a nested evaluation context that shares the same search graph as the
339352
/// one passed in. This is suitable for evaluation, granted that the search graph
340353
/// has had the nested goal recorded on its stack. This method only be used by
@@ -598,15 +611,31 @@ where
598611
#[instrument(level = "trace", skip(self))]
599612
pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolution> {
600613
let mut response = Ok(Certainty::overflow(false));
601-
for _ in 0..FIXPOINT_STEP_LIMIT {
602-
// FIXME: This match is a bit ugly, it might be nice to change the inspect
603-
// stuff to use a closure instead. which should hopefully simplify this a bit.
604-
match self.evaluate_added_goals_step() {
614+
for i in 0..FIXPOINT_STEP_LIMIT {
615+
debug!(?i, ?self.nested_goals, "try_evaluate_added_goals_step");
616+
let evaluate_step_result = if i == 0 {
617+
self.with_capped_depth(4, |this| this.evaluate_added_goals_step())
618+
} else {
619+
self.evaluate_added_goals_step()
620+
};
621+
match evaluate_step_result {
605622
Ok(Some(cert)) => {
606-
response = Ok(cert);
607-
break;
623+
if i == 0 {
624+
for (_, _, stalled_on) in &mut self.nested_goals {
625+
*stalled_on = None;
626+
}
627+
} else {
628+
response = Ok(cert);
629+
break;
630+
}
631+
}
632+
Ok(None) => {
633+
if i == 0 {
634+
for (_, _, stalled_on) in &mut self.nested_goals {
635+
*stalled_on = None;
636+
}
637+
}
608638
}
609-
Ok(None) => {}
610639
Err(NoSolution) => {
611640
response = Err(NoSolution);
612641
break;

compiler/rustc_next_trait_solver/src/solve/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ where
269269
}
270270

271271
fn bail_with_ambiguity(&mut self, responses: &[CanonicalResponse<I>]) -> CanonicalResponse<I> {
272-
debug_assert!(responses.len() > 1);
272+
debug_assert!(responses.len() > 0);
273273
let maybe_cause = responses.iter().fold(MaybeCause::Ambiguity, |maybe_cause, response| {
274274
// Pull down the certainty of `Certainty::Yes` to ambiguity when combining
275275
// these responses, b/c we're combining more than one response and this we

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,12 @@ where
13781378
.map(|c| c.result)
13791379
.collect();
13801380
return if let Some(response) = self.try_merge_responses(&where_bounds) {
1381-
Ok((response, Some(TraitGoalProvenVia::ParamEnv)))
1381+
let proven_via = if response.value.certainty == Certainty::Yes {
1382+
Some(TraitGoalProvenVia::ParamEnv)
1383+
} else {
1384+
None
1385+
};
1386+
Ok((response, proven_via))
13821387
} else {
13831388
Ok((self.bail_with_ambiguity(&where_bounds), None))
13841389
};
@@ -1391,7 +1396,12 @@ where
13911396
.map(|c| c.result)
13921397
.collect();
13931398
return if let Some(response) = self.try_merge_responses(&alias_bounds) {
1394-
Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1399+
let proven_via = if response.value.certainty == Certainty::Yes {
1400+
Some(TraitGoalProvenVia::AliasBound)
1401+
} else {
1402+
None
1403+
};
1404+
Ok((response, proven_via))
13951405
} else {
13961406
Ok((self.bail_with_ambiguity(&alias_bounds), None))
13971407
};

compiler/rustc_type_ir/src/search_graph/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::collections::hash_map::Entry;
1717
use std::fmt::Debug;
1818
use std::hash::Hash;
1919
use std::marker::PhantomData;
20+
use std::mem;
2021

2122
use derive_where::derive_where;
2223
#[cfg(feature = "nightly")]
@@ -521,6 +522,11 @@ enum UpdateParentGoalCtxt<'a, X: Cx> {
521522
ProvisionalCacheHit,
522523
}
523524

525+
pub struct WithCappedDepthInfo {
526+
encountered_overflow: bool,
527+
available_depth: AvailableDepth,
528+
}
529+
524530
impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
525531
pub fn new(root_depth: usize) -> SearchGraph<D> {
526532
Self {
@@ -594,6 +600,25 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
594600
stack.cycle_step_kinds(head).fold(step_kind_to_head, |curr, step| curr.extend(step))
595601
}
596602

603+
pub fn with_capped_depth_start(&mut self, max_depth: usize) -> Option<WithCappedDepthInfo> {
604+
let entry = self.stack.last_mut().unwrap();
605+
if max_depth < entry.available_depth.0 {
606+
let encountered_overflow = entry.encountered_overflow;
607+
let available_depth =
608+
mem::replace(&mut entry.available_depth, AvailableDepth(max_depth));
609+
Some(WithCappedDepthInfo { encountered_overflow, available_depth })
610+
} else {
611+
None
612+
}
613+
}
614+
615+
pub fn with_capped_depth_end(&mut self, info: WithCappedDepthInfo) {
616+
let entry = self.stack.last_mut().unwrap();
617+
entry.encountered_overflow = info.encountered_overflow;
618+
entry.available_depth = info.available_depth;
619+
self.provisional_cache.clear();
620+
}
621+
597622
/// Probably the most involved method of the whole solver.
598623
///
599624
/// While goals get computed via `D::compute_goal`, this function handles

0 commit comments

Comments
 (0)