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 | 110 |
1 files changed, 110 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..66da6d5400 --- /dev/null +++ b/crates/hir-ty/src/next_solver/format_proof_tree.rs @@ -0,0 +1,110 @@ +use rustc_type_ir::{solve::GoalSource, solve::inspect::GoalEvaluation}; +use serde_derive::{Deserialize, Serialize}; + +use crate::next_solver::inspect::{InspectCandidate, InspectGoal}; +use crate::next_solver::{AnyImplId, infer::InferCtxt}; +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 hir_def::{Lookup, src::HasSource}; + use rustc_type_ir::solve::CandidateSource; + let db = self.infcx.interner.db; + match source { + CandidateSource::Impl(impl_def_id) => match impl_def_id { + AnyImplId::ImplId(impl_def_id) => { + let impl_src = impl_def_id.lookup(db).source(db); + Some(impl_src.value.to_string()) + } + AnyImplId::BuiltinDeriveImplId(impl_id) => { + let impl_loc = impl_id.loc(db); + let adt_src = match impl_loc.adt { + hir_def::AdtId::StructId(adt) => { + adt.loc(db).source(db).value.to_string() + } + hir_def::AdtId::UnionId(adt) => { + adt.loc(db).source(db).value.to_string() + } + hir_def::AdtId::EnumId(adt) => { + adt.loc(db).source(db).value.to_string() + } + }; + Some(format!("#[derive(${})]\n{}", impl_loc.trait_.name(), adt_src)) + } + }, + _ => None, + } + } + _ => None, + } + } +} |