1use macros::{TypeFoldable, TypeVisitable};
9use rustc_type_ir::{PredicatePolarity, inherent::IntoKind};
10
11use crate::{
12 Span,
13 next_solver::{
14 ClauseKind, DbInterner, PredicateKind, StoredTraitRef, TraitPredicate,
15 infer::{
16 errors::{FulfillmentError, FulfillmentErrorCode},
17 select::SelectionError,
18 },
19 },
20};
21
22#[derive(Debug, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
23pub struct SolverDiagnostic {
24 pub span: Span,
25 pub kind: SolverDiagnosticKind,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
29pub enum SolverDiagnosticKind {
30 TraitUnimplemented {
31 trait_predicate: StoredTraitPredicate,
32 parent_trait_predicates: Vec<StoredTraitPredicate>,
33 },
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
37pub struct StoredTraitPredicate {
38 pub trait_ref: StoredTraitRef,
39 pub polarity: PredicatePolarity,
40}
41
42impl StoredTraitPredicate {
43 #[inline]
44 pub fn get<'db>(&'db self, interner: DbInterner<'db>) -> TraitPredicate<'db> {
45 TraitPredicate { polarity: self.polarity, trait_ref: self.trait_ref.get(interner) }
46 }
47}
48
49impl SolverDiagnostic {
50 pub fn from_fulfillment_error(error: &FulfillmentError<'_>) -> Option<Self> {
51 let span = error.obligation.cause.span();
52 if span.is_dummy() {
53 return None;
54 }
55
56 let kind = match &error.code {
58 FulfillmentErrorCode::Select(SelectionError::Unimplemented) => {
59 match error.obligation.predicate.kind().skip_binder() {
60 PredicateKind::Clause(ClauseKind::Trait(trait_pred)) => {
61 handle_trait_unimplemented(error, trait_pred)?
62 }
63 _ => return None,
64 }
65 }
66 _ => return None,
67 };
68 Some(SolverDiagnostic { span, kind })
69 }
70}
71
72fn handle_trait_unimplemented<'db>(
73 error: &FulfillmentError<'db>,
74 trait_pred: TraitPredicate<'db>,
75) -> Option<SolverDiagnosticKind> {
76 let trait_predicate = StoredTraitPredicate {
77 trait_ref: StoredTraitRef::new(trait_pred.trait_ref),
78 polarity: trait_pred.polarity,
79 };
80
81 let mut parent_trait_predicates = error
82 .parent_trait_obligations
83 .iter()
84 .filter_map(|predicate| predicate.as_trait_clause())
85 .map(|trait_predicate| {
86 let trait_predicate = trait_predicate.skip_binder();
87 StoredTraitPredicate {
88 trait_ref: StoredTraitRef::new(trait_predicate.trait_ref),
89 polarity: trait_predicate.polarity,
90 }
91 })
92 .collect::<Vec<_>>();
93 parent_trait_predicates.reverse();
94
95 Some(SolverDiagnosticKind::TraitUnimplemented { trait_predicate, parent_trait_predicates })
96}