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.rs | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index fd08528e86..fcb97ab34e 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -32,11 +32,16 @@ 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::{ProofTreeData, 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 +2315,38 @@ 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) => { + thread_local! { + static RESULT: RefCell<Vec<ProofTreeData>> = const { RefCell::new(Vec::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); + RESULT.with(|ctx| ctx.borrow_mut().push(data)); + } + }), + ); + let data: Vec<ProofTreeData> = + RESULT.with(|data| data.borrow_mut().drain(..).collect()); + let data = serde_json::to_string_pretty(&data).unwrap_or_else(|_| "[]".to_owned()); + Some(data) + } + _ => None, + } + } } // FIXME This can't be the best way to do this |