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.rs110
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,
+ }
+ }
+}