Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/semantics.rs')
-rw-r--r--crates/hir/src/semantics.rs34
1 files changed, 33 insertions, 1 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index fd08528e86..60418b1dad 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -8,6 +8,7 @@ use std::{
convert::Infallible,
fmt, iter, mem,
ops::{self, ControlFlow, Not},
+ sync::Mutex,
};
use base_db::FxIndexSet;
@@ -32,11 +33,13 @@ use hir_expand::{
use hir_ty::{
InferenceResult,
diagnostics::{unsafe_operations, unsafe_operations_for_body},
- next_solver::DbInterner,
+ infer_query_with_inspect,
+ next_solver::{DbInterner, Span, format_proof_tree::dump_proof_tree_structured},
};
use intern::{Interned, Symbol, sym};
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_type_ir::inherent::Span as _;
use smallvec::{SmallVec, smallvec};
use span::{FileId, SyntaxContext};
use stdx::{TupleExt, always};
@@ -2310,6 +2313,35 @@ impl<'db> SemanticsImpl<'db> {
Some(locals)
}
+
+ pub fn get_failed_obligations(&self, token: SyntaxToken) -> Option<String> {
+ let node = token.parent()?;
+ let node = self.find_file(&node);
+
+ let container = self.with_ctx(|ctx| ctx.find_container(node))?;
+
+ match container {
+ ChildContainer::DefWithBodyId(def) => {
+ static RESULT: Mutex<String> = Mutex::new(String::new());
+ infer_query_with_inspect(
+ self.db,
+ def,
+ Some(|infer_ctxt, _obligation, result, proof_tree| {
+ if result.is_err()
+ && let Some(tree) = proof_tree
+ {
+ let data = dump_proof_tree_structured(tree, Span::dummy(), infer_ctxt);
+ let data = serde_json::to_string_pretty(&data)
+ .unwrap_or_else(|_| "{}".to_string());
+ *RESULT.lock().unwrap() = data;
+ }
+ }),
+ );
+ RESULT.lock().ok().map(|s| (*s).clone())
+ }
+ _ => None,
+ }
+ }
}
// FIXME This can't be the best way to do this