rustc_infer/traits/
util.rs1use rustc_data_structures::fx::FxHashSet;
2pub use rustc_middle::ty::elaborate::*;
3use rustc_middle::ty::{self, TyCtxt, Unnormalized};
4use rustc_span::{Ident, Span};
5
6use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation};
7
8pub fn anonymize_predicate<'tcx>(
9 tcx: TyCtxt<'tcx>,
10 pred: ty::Predicate<'tcx>,
11) -> ty::Predicate<'tcx> {
12 let new = tcx.anonymize_bound_vars(pred.kind());
13 tcx.reuse_or_mk_predicate(pred, new)
14}
15
16pub struct PredicateSet<'tcx> {
17 tcx: TyCtxt<'tcx>,
18 set: FxHashSet<ty::Predicate<'tcx>>,
19}
20
21impl<'tcx> PredicateSet<'tcx> {
22 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
23 Self { tcx, set: Default::default() }
24 }
25
26 pub fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
34 self.set.insert(anonymize_predicate(self.tcx, pred))
45 }
46}
47
48impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
49 fn extend<I: IntoIterator<Item = ty::Predicate<'tcx>>>(&mut self, iter: I) {
50 let iter = iter.into_iter();
51 self.set.reserve(iter.size_hint().0);
52 for pred in iter {
53 self.insert(pred);
54 }
55 }
56
57 fn extend_one(&mut self, pred: ty::Predicate<'tcx>) {
58 self.insert(pred);
59 }
60
61 fn extend_reserve(&mut self, additional: usize) {
62 Extend::<ty::Predicate<'tcx>>::extend_reserve(&mut self.set, additional);
63 }
64}
65
66impl<'tcx> Elaboratable<TyCtxt<'tcx>> for PredicateObligation<'tcx> {
69 fn predicate(&self) -> ty::Predicate<'tcx> {
70 self.predicate
71 }
72
73 fn child(&self, clause: ty::Clause<'tcx>) -> Self {
74 Obligation {
75 cause: self.cause.clone(),
76 param_env: self.param_env,
77 recursion_depth: 0,
78 predicate: clause.as_predicate(),
79 }
80 }
81
82 fn child_with_derived_cause(
83 &self,
84 clause: ty::Clause<'tcx>,
85 span: Span,
86 parent_trait_pred: ty::PolyTraitClause<'tcx>,
87 index: usize,
88 ) -> Self {
89 let cause = self.cause.clone().derived_cause(parent_trait_pred, |derived| {
90 ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
91 derived,
92 impl_or_alias_def_id: parent_trait_pred.def_id(),
93 impl_def_clause_index: Some(index),
94 span,
95 }))
96 });
97 Obligation {
98 cause,
99 param_env: self.param_env,
100 recursion_depth: 0,
101 predicate: clause.as_predicate(),
102 }
103 }
104}
105
106pub fn transitive_bounds_that_define_assoc_item<'tcx>(
112 tcx: TyCtxt<'tcx>,
113 trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
114 assoc_name: Ident,
115) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
116 let mut seen = FxHashSet::default();
117 let mut stack: Vec<_> = trait_refs.collect();
118
119 std::iter::from_fn(move || {
120 while let Some(trait_ref) = stack.pop() {
121 if !seen.insert(tcx.anonymize_bound_vars(trait_ref)) {
122 continue;
123 }
124
125 stack.extend(
126 tcx.explicit_supertraits_containing_assoc_item((trait_ref.def_id(), assoc_name))
127 .iter_identity_copied()
128 .map(Unnormalized::skip_norm_wip)
129 .map(|(clause, _)| clause.instantiate_supertrait(tcx, trait_ref))
130 .filter_map(|clause| clause.as_trait_clause())
131 .filter(|clause| clause.polarity() == ty::ClausePolarity::Positive)
132 .map(|clause| clause.map_bound(|clause| clause.trait_ref)),
133 );
134
135 return Some(trait_ref);
136 }
137
138 None
139 })
140}