Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_type_ir::inherent::*;
use rustc_type_ir::region_constraint::RegionConstraint;
use rustc_type_ir::relate::Relate;
use rustc_type_ir::relate::solver_relating::RelateExt;
use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind};
use rustc_type_ir::search_graph::{CandidateHeadUsages, IncreaseDepthForNested, PathKind};
use rustc_type_ir::solve::{
AccessedOpaques, ExternalRegionConstraints, FetchEligibleAssocItemResponse, MaybeInfo,
NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunCondition,
Expand Down Expand Up @@ -483,7 +483,7 @@ where
stalled_on: Option<GoalStalledOn<I>>,
) -> Result<GoalEvaluation<I>, NoSolutionOrRerunNonErased> {
let (normalization_nested_goals, goal_evaluation) =
self.evaluate_goal_raw(source, goal, stalled_on)?;
self.evaluate_goal_raw(source, goal, stalled_on, IncreaseDepthForNested::Yes)?;
assert!(normalization_nested_goals.is_empty());
Ok(goal_evaluation)
}
Expand Down Expand Up @@ -575,6 +575,7 @@ where
source: GoalSource,
goal: Goal<I, I::Predicate>,
stalled_on: Option<GoalStalledOn<I>>,
increase_depth_for_nested: IncreaseDepthForNested,
) -> Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolutionOrRerunNonErased> {
if let RerunStalled::WontMakeProgress(stalled_certainty) =
self.rerunning_stalled_goal_may_make_progress(stalled_on.as_ref())
Expand Down Expand Up @@ -652,6 +653,7 @@ where
self.cx(),
canonical_goal,
step_kind,
increase_depth_for_nested,
&mut inspect::ProofTreeBuilder::new_noop(),
);

Expand Down Expand Up @@ -691,6 +693,7 @@ where
self.cx(),
canonical_goal,
step_kind,
increase_depth_for_nested,
&mut inspect::ProofTreeBuilder::new_noop(),
);
assert!(
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod free_alias;
mod inherent;
mod opaque_types;

use rustc_type_ir::search_graph::IncreaseDepthForNested;
use rustc_type_ir::solve::QueryResultOrRerunNonErased;
use rustc_type_ir::{self as ty, Interner, ProjectionPredicate};
use tracing::{instrument, trace};
Expand Down Expand Up @@ -67,7 +68,19 @@ where
let (
NestedNormalizationGoals(nested_goals),
GoalEvaluation { goal: _, certainty, stalled_on: _, has_changed: _ },
) = self.evaluate_goal_raw(GoalSource::TypeRelating, normalizes_to, None)?;
) = self.evaluate_goal_raw(
GoalSource::TypeRelating,
normalizes_to,
None,
// We don't increase depth for nested goals for this `NormalizesTo` goal, as
// evaluating `NormalizesTo` is an extra step only exists in the new solver
// that behaves like a function call rather than an independent nested goal
// evaluation, so increasing the depth may end up regressions which hit the
// recursion limits for crates compiled well with the old solver. Furthermore,
// those nested goals from `NormalizesTo` will be evaluated again as the
// caller's nested goals with increased depths anyway.
IncreaseDepthForNested::No,
)?;

trace!(?nested_goals);

Expand Down
41 changes: 31 additions & 10 deletions compiler/rustc_type_ir/src/search_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ impl CandidateHeadUsages {
}
}

#[derive(Debug, Clone, Copy)]
pub enum IncreaseDepthForNested {
Yes,
No,
}

#[derive(Debug, Clone, Copy)]
struct AvailableDepth(usize);
impl AvailableDepth {
Expand All @@ -276,6 +282,13 @@ impl AvailableDepth {
stack: &Stack<D::Cx>,
) -> Option<AvailableDepth> {
if let Some(last) = stack.last() {
match last.increase_depth_for_nested {
IncreaseDepthForNested::Yes => {}
IncreaseDepthForNested::No => {
return Some(last.available_depth);
}
}

if last.available_depth.0 == 0 {
return None;
}
Expand Down Expand Up @@ -566,7 +579,7 @@ impl<X: Cx> EvaluationResult<X> {
encountered_overflow,
// Unlike `encountered_overflow`, we share `heads`, `required_depth`,
// and `nested_goals` between evaluations.
required_depth: final_entry.required_depth,
required_depth: final_entry.required_depth(),
heads: final_entry.heads,
nested_goals: final_entry.nested_goals,
// We only care about the final result.
Expand Down Expand Up @@ -619,13 +632,17 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
fn update_parent_goal(
stack: &mut Stack<X>,
step_kind_from_parent: PathKind,
required_depth_for_nested: usize,
min_reachable_for_nested: Option<AvailableDepth>,
heads: impl Iterator<Item = (StackDepth, CycleHead)>,
encountered_overflow: bool,
context: UpdateParentGoalCtxt<'_, X>,
) {
if let Some((parent_index, parent)) = stack.last_mut_with_index() {
parent.required_depth = parent.required_depth.max(required_depth_for_nested + 1);
if let Some(min_reachable_for_nested) = min_reachable_for_nested {
parent.min_reached_available_depth = AvailableDepth(
parent.min_reached_available_depth.0.min(min_reachable_for_nested.0),
);
}
parent.encountered_overflow |= encountered_overflow;

for (head_index, head) in heads {
Expand Down Expand Up @@ -739,8 +756,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
input,
step_kind_from_parent,
available_depth,
min_reached_available_depth: available_depth,
provisional_result: None,
required_depth: 0,
increase_depth_for_nested: IncreaseDepthForNested::Yes,
heads: Default::default(),
encountered_overflow: false,
usages: None,
Expand All @@ -761,6 +779,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
cx: X,
input: X::Input,
step_kind_from_parent: PathKind,
increase_depth_for_nested: IncreaseDepthForNested,
inspect: &mut D::ProofTreeBuilder,
) -> X::Result {
let Some(available_depth) =
Expand Down Expand Up @@ -816,7 +835,8 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
step_kind_from_parent,
available_depth,
provisional_result: None,
required_depth: 0,
min_reached_available_depth: available_depth,
increase_depth_for_nested,
heads: Default::default(),
encountered_overflow: false,
usages: None,
Expand All @@ -838,7 +858,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
Self::update_parent_goal(
&mut self.stack,
step_kind_from_parent,
evaluation_result.required_depth,
Some(AvailableDepth(available_depth.0 - evaluation_result.required_depth)),
evaluation_result.heads.iter(),
evaluation_result.encountered_overflow,
UpdateParentGoalCtxt::Ordinary(&evaluation_result.nested_goals),
Expand Down Expand Up @@ -1116,7 +1136,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
Self::update_parent_goal(
&mut self.stack,
step_kind_from_parent,
0,
None,
heads.iter(),
encountered_overflow,
UpdateParentGoalCtxt::ProvisionalCacheHit,
Expand Down Expand Up @@ -1239,7 +1259,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
Self::update_parent_goal(
&mut self.stack,
step_kind_from_parent,
required_depth,
Some(AvailableDepth(available_depth.0 - required_depth)),
heads,
encountered_overflow,
UpdateParentGoalCtxt::Ordinary(nested_goals),
Expand Down Expand Up @@ -1271,7 +1291,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
Self::update_parent_goal(
&mut self.stack,
step_kind_from_parent,
0,
None,
iter::once((head_index, head)),
false,
UpdateParentGoalCtxt::CycleOnStack(input),
Expand Down Expand Up @@ -1407,7 +1427,8 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
provisional_result: Some(result),
// We can keep these goals from previous iterations as they are only
// ever read after finalizing this evaluation.
required_depth: stack_entry.required_depth,
min_reached_available_depth: stack_entry.min_reached_available_depth,
increase_depth_for_nested: stack_entry.increase_depth_for_nested,
heads: stack_entry.heads,
nested_goals: stack_entry.nested_goals,
// We reset these two fields when rerunning this goal. We could
Expand Down
25 changes: 22 additions & 3 deletions compiler/rustc_type_ir/src/search_graph/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use derive_where::derive_where;
use rustc_index::IndexVec;

use crate::search_graph::{
AvailableDepth, CandidateHeadUsages, Cx, CycleHeads, HeadUsages, NestedGoals, PathKind,
AvailableDepth, CandidateHeadUsages, Cx, CycleHeads, HeadUsages, IncreaseDepthForNested,
NestedGoals, PathKind,
};

rustc_index::newtype_index! {
Expand All @@ -28,8 +29,20 @@ pub(super) struct StackEntry<X: Cx> {
/// The available depth of a given goal, immutable.
pub available_depth: AvailableDepth,

/// The maximum depth required while evaluating this goal.
pub required_depth: usize,
/// The minimum available depth encountered while evaluating this goal's nested goals.
/// If there's no nested goal, this is equal to the `available_depth`.
pub min_reached_available_depth: AvailableDepth,

/// Whether evaluating nested goals of a given goal should increase the depth.
///
/// Normally, it should be `Yes`, but among rustc's predicate goals, `normalizes-to`
/// goals are exceptions. They act like functions that used for normalizing associated
/// terms while evaluating projection goals and since their expected terms are always fully
/// unconstrained intentionally, they often return ambiguous nested goals to the caller's
/// context. As these nested goals are evaluated again in the caller's context, we don't
/// want to increase depths when they are evaluated as nested goals for `normalizes-to`
/// goals, otherwise we will encounter recursion limit overflows more often.
pub increase_depth_for_nested: IncreaseDepthForNested,

/// Starts out as `None` and gets set when rerunning this
/// goal in case we encounter a cycle.
Expand Down Expand Up @@ -57,6 +70,12 @@ pub(super) struct StackEntry<X: Cx> {
pub nested_goals: NestedGoals<X>,
}

impl<X: Cx> StackEntry<X> {
pub(super) fn required_depth(&self) -> usize {
self.available_depth.0 - self.min_reached_available_depth.0
}
}

/// The stack of goals currently being computed.
///
/// An element is *deeper* in the stack if its index is *lower*.
Expand Down
Loading