Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/format_proof_tree.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/format_proof_tree.rs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/crates/hir-ty/src/next_solver/format_proof_tree.rs b/crates/hir-ty/src/next_solver/format_proof_tree.rs new file mode 100644 index 0000000000..59fb0d65c5 --- /dev/null +++ b/crates/hir-ty/src/next_solver/format_proof_tree.rs @@ -0,0 +1,93 @@ +use rustc_type_ir::{solve::GoalSource, solve::inspect::GoalEvaluation}; +use serde_derive::{Deserialize, Serialize}; + +use crate::next_solver::infer::InferCtxt; +use crate::next_solver::inspect::{InspectCandidate, InspectGoal}; +use crate::next_solver::{DbInterner, Span}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProofTreeData { + pub goal: String, + pub result: String, + pub depth: usize, + pub candidates: Vec<CandidateData>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CandidateData { + pub kind: String, + pub result: String, + pub impl_header: Option<String>, + pub nested_goals: Vec<ProofTreeData>, +} + +pub fn dump_proof_tree_structured<'db>( + proof_tree: GoalEvaluation<DbInterner<'db>>, + _span: Span, + infcx: &InferCtxt<'db>, +) -> ProofTreeData { + let goal_eval = InspectGoal::new(infcx, 0, proof_tree, None, GoalSource::Misc); + let mut serializer = ProofTreeSerializer::new(infcx); + serializer.serialize_goal(&goal_eval) +} + +struct ProofTreeSerializer<'a, 'db> { + infcx: &'a InferCtxt<'db>, +} + +impl<'a, 'db> ProofTreeSerializer<'a, 'db> { + fn new(infcx: &'a InferCtxt<'db>) -> Self { + Self { infcx } + } + + fn serialize_goal(&mut self, goal: &InspectGoal<'_, 'db>) -> ProofTreeData { + let candidates = goal.candidates(); + let candidates_data: Vec<CandidateData> = + candidates.iter().map(|c| self.serialize_candidate(c)).collect(); + + ProofTreeData { + goal: format!("{:?}", goal.goal()), + result: format!("{:?}", goal.result()), + depth: goal.depth(), + candidates: candidates_data, + } + } + + fn serialize_candidate(&mut self, candidate: &InspectCandidate<'_, 'db>) -> CandidateData { + let kind = candidate.kind(); + let impl_header = self.get_impl_header(candidate); + + let mut nested = Vec::new(); + self.infcx.probe(|_| { + for nested_goal in candidate.instantiate_nested_goals() { + nested.push(self.serialize_goal(&nested_goal)); + } + }); + + CandidateData { + kind: format!("{:?}", kind), + result: format!("{:?}", candidate.result()), + impl_header, + nested_goals: nested, + } + } + + fn get_impl_header(&self, candidate: &InspectCandidate<'_, 'db>) -> Option<String> { + use rustc_type_ir::solve::inspect::ProbeKind; + match candidate.kind() { + ProbeKind::TraitCandidate { source, .. } => { + use rustc_type_ir::solve::CandidateSource; + match source { + CandidateSource::Impl(impl_def_id) => { + use hir_def::{Lookup, src::HasSource}; + let db = self.infcx.interner.db; + let impl_src = impl_def_id.0.lookup(db).source(db); + Some(impl_src.value.to_string()) + } + _ => None, + } + } + _ => None, + } + } +} |