Skip to content

Commit

Permalink
Convert ProofTreeVisitor to use VisitorResult
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarcho committed Mar 5, 2024
1 parent ea9ae30 commit 228eb38
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 31 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#![allow(rustc::untranslatable_diagnostic)]
#![feature(assert_matches)]
#![feature(associated_type_bounds)]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(extract_if)]
Expand Down
47 changes: 23 additions & 24 deletions compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
/// An infrastructure to mechanically analyse proof trees.
///
/// It is unavoidable that this representation is somewhat
/// lossy as it should hide quite a few semantically relevant things,
/// e.g. canonicalization and the order of nested goals.
///
/// @lcnr: However, a lot of the weirdness here is not strictly necessary
/// and could be improved in the future. This is mostly good enough for
/// coherence right now and was annoying to implement, so I am leaving it
/// as is until we start using it for something else.
use std::ops::ControlFlow;

//! An infrastructure to mechanically analyse proof trees.
//!
//! It is unavoidable that this representation is somewhat
//! lossy as it should hide quite a few semantically relevant things,
//! e.g. canonicalization and the order of nested goals.
//!
//! @lcnr: However, a lot of the weirdness here is not strictly necessary
//! and could be improved in the future. This is mostly good enough for
//! coherence right now and was annoying to implement, so I am leaving it
//! as is until we start using it for something else.

use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
use rustc_infer::infer::InferCtxt;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{inspect, QueryResult};
Expand Down Expand Up @@ -53,10 +54,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
/// to also use it to compute the most relevant goal
/// for fulfillment errors. Will do that once we actually
/// need it.
pub fn visit_nested<V: ProofTreeVisitor<'tcx>>(
&self,
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
pub fn visit_nested<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
// HACK: An arbitrary cutoff to avoid dealing with overflow and cycles.
if self.goal.depth <= 10 {
let infcx = self.goal.infcx;
Expand All @@ -75,17 +73,18 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
for &goal in &instantiated_goals {
let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes);
let proof_tree = proof_tree.unwrap();
visitor.visit_goal(&InspectGoal::new(
try_visit!(visitor.visit_goal(&InspectGoal::new(
infcx,
self.goal.depth + 1,
&proof_tree,
))?;
)));
}

ControlFlow::Continue(())
})?;
V::Result::output()
})
} else {
V::Result::output()
}
ControlFlow::Continue(())
}
}

Expand Down Expand Up @@ -202,9 +201,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {

/// The public API to interact with proof trees.
pub trait ProofTreeVisitor<'tcx> {
type BreakTy;
type Result: VisitorResult = ();

fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy>;
fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result;
}

#[extension(pub trait ProofTreeInferCtxtExt<'tcx>)]
Expand All @@ -213,7 +212,7 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
goal: Goal<'tcx, ty::Predicate<'tcx>>,
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
) -> V::Result {
self.probe(|_| {
let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
let proof_tree = proof_tree.unwrap();
Expand Down
11 changes: 4 additions & 7 deletions compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1023,18 +1023,17 @@ struct AmbiguityCausesVisitor<'a, 'tcx> {
}

impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
type BreakTy = !;
fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) {
let infcx = goal.infcx();
for cand in goal.candidates() {
cand.visit_nested(self)?;
cand.visit_nested(self);
}
// When searching for intercrate ambiguity causes, we only need to look
// at ambiguous goals, as for others the coherence unknowable candidate
// was irrelevant.
match goal.result() {
Ok(Certainty::Maybe(_)) => {}
Ok(Certainty::Yes) | Err(NoSolution) => return ControlFlow::Continue(()),
Ok(Certainty::Yes) | Err(NoSolution) => return,
}

let Goal { param_env, predicate } = goal.goal();
Expand All @@ -1051,7 +1050,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
{
proj.projection_ty.trait_ref(infcx.tcx)
}
_ => return ControlFlow::Continue(()),
_ => return,
};

// Add ambiguity causes for reservation impls.
Expand Down Expand Up @@ -1151,8 +1150,6 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
if let Some(ambiguity_cause) = ambiguity_cause {
self.causes.insert(ambiguity_cause);
}

ControlFlow::Continue(())
}
}

Expand Down

0 comments on commit 228eb38

Please sign in to comment.