Skip to main content

rustc_type_ir/
param_env.rs

1use std::marker::PhantomData;
2
3pub use clause_filter::NoClauses;
4use clause_filter::*;
5pub use iterator::CallerBoundsIterator;
6use output_as::*;
7use polarity_filter::*;
8use self_ty_filter::*;
9use trait_filter::*;
10
11use crate::inherent::*;
12use crate::lang_items::SolverTraitLangItem;
13use crate::{Binder, ClauseKind, ClausePolarity, Interner, TraitClause, Upcast};
14
15#[must_use]
16pub struct CallerBoundsAccessor<I, Iter, CF>
17where
18    I: Interner,
19    Iter: Iterator<Item = I::Clause>,
20    CF: ClauseFilter,
21{
22    clauses: Iter,
23    clause_filter: CF,
24    cx: PhantomData<I>,
25}
26
27impl<I, Iter> CallerBoundsAccessor<I, Iter, NoClauses>
28where
29    I: Interner,
30    Iter: Iterator<Item = I::Clause>,
31{
32    #[inline]
33    pub fn new(clauses: Iter) -> Self {
34        Self { clauses, clause_filter: NoClauses, cx: PhantomData }
35    }
36}
37
38mod iterator {
39    use super::*;
40    use crate::param_env::output_as::OutputAs;
41
42    pub trait CallerBoundsIterator<I, Iter>
43    where
44        I: Interner,
45        Iter: Iterator<Item = I::Clause>,
46    {
47        type Item;
48        /// Note: likely less efficient than staying in `CallerBoundsIterator` land.
49        fn iter(self) -> impl Iterator<Item = Self::Item>;
50    }
51    impl<I, Iter> CallerBoundsIterator<I, Iter> for CallerBoundsAccessor<I, Iter, NonTraitClauses>
52    where
53        I: Interner,
54        Iter: Iterator<Item = I::Clause>,
55    {
56        type Item = I::Clause;
57
58        #[inline]
59        fn iter(self) -> impl Iterator<Item = Self::Item> {
60            self.clauses.filter(|&i| !#[allow(non_exhaustive_omitted_patterns)] match i.kind().skip_binder() {
    ClauseKind::Trait(_) => true,
    _ => false,
}matches!(i.kind().skip_binder(), ClauseKind::Trait(_)))
61        }
62    }
63
64    impl<I, Iter> CallerBoundsIterator<I, Iter> for CallerBoundsAccessor<I, Iter, AllClauses>
65    where
66        I: Interner,
67        Iter: Iterator<Item = I::Clause>,
68    {
69        type Item = I::Clause;
70
71        #[inline]
72        fn iter(self) -> impl Iterator<Item = Self::Item> {
73            self.clauses
74        }
75    }
76
77    #[inline]
78    fn filter_trait_clause_helper<I, P, S, T, O>(
79        filter: &TraitClauses<I, P, S, T, O>,
80        clause: TraitClause<I>,
81    ) -> bool
82    where
83        I: Interner,
84        P: PolarityFilter,
85        S: SelfTyFilter<I>,
86        T: TraitFilter<I>,
87        O: OutputAs<I>,
88    {
89        let TraitClauses { cx: _, polarity_filter, self_type_filter, trait_filter, output: _ } =
90            filter;
91        polarity_filter.allow_polarity(clause.polarity)
92            && self_type_filter.allow_self_ty(clause.self_ty())
93            && trait_filter.allow_clause(clause)
94    }
95
96    impl<I, Iter, P, S, T, O> CallerBoundsIterator<I, Iter>
97        for CallerBoundsAccessor<I, Iter, TraitClauses<I, P, S, T, O>>
98    where
99        I: Interner,
100        Iter: Iterator<Item = I::Clause>,
101        P: PolarityFilter,
102        S: SelfTyFilter<I>,
103        T: TraitFilter<I>,
104        O: OutputAs<I>,
105    {
106        type Item = O::Output;
107
108        #[inline]
109        fn iter(self) -> impl Iterator<Item = Self::Item> {
110            self.clauses.filter_map(move |clause| {
111                let kind = clause.kind();
112                match kind.skip_binder() {
113                    ClauseKind::Trait(trait_clause)
114                        if filter_trait_clause_helper(&self.clause_filter, trait_clause) =>
115                    {
116                        Some(O::construct_from_trait_clause(
117                            kind.rebind(trait_clause),
118                            self.clause_filter.cx,
119                        ))
120                    }
121                    _ => None,
122                }
123            })
124        }
125    }
126}
127
128mod clause_filter {
129    use super::*;
130
131    pub trait ClauseFilter {}
132
133    pub struct NoClauses;
134    impl ClauseFilter for NoClauses {}
135
136    pub struct NonTraitClauses;
137    impl ClauseFilter for NonTraitClauses {}
138
139    pub struct TraitClauses<I, P, S, T, O> {
140        pub cx: I,
141        pub polarity_filter: P,
142        pub self_type_filter: S,
143        pub trait_filter: T,
144        pub output: O,
145    }
146
147    impl<I, P, S, T, O> ClauseFilter for TraitClauses<I, P, S, T, O> {}
148
149    pub struct AllClauses;
150    impl ClauseFilter for AllClauses {}
151
152    impl<I, Iter> CallerBoundsAccessor<I, Iter, NoClauses>
153    where
154        I: Interner,
155        Iter: Iterator<Item = I::Clause>,
156    {
157        #[inline]
158        pub fn non_trait_clauses(self) -> CallerBoundsAccessor<I, Iter, NonTraitClauses> {
159            CallerBoundsAccessor {
160                clauses: self.clauses,
161                clause_filter: NonTraitClauses,
162                cx: PhantomData,
163            }
164        }
165
166        #[inline]
167        pub fn trait_clauses(
168            self,
169            cx: I,
170        ) -> CallerBoundsAccessor<I, Iter, TraitClauses<I, (), (), (), OutputAsTraitClause>>
171        {
172            CallerBoundsAccessor {
173                clauses: self.clauses,
174                clause_filter: TraitClauses {
175                    polarity_filter: (),
176                    self_type_filter: (),
177                    trait_filter: (),
178                    output: OutputAsTraitClause,
179                    cx,
180                },
181                cx: PhantomData,
182            }
183        }
184
185        /// Warning: may be a performance hazzard!
186        #[inline]
187        // FIXME: asking for _cx here is useful down the line.
188        pub fn all_clauses(self, _cx: I) -> CallerBoundsAccessor<I, Iter, AllClauses> {
189            CallerBoundsAccessor {
190                clauses: self.clauses,
191                clause_filter: AllClauses,
192                cx: PhantomData,
193            }
194        }
195    }
196}
197
198mod polarity_filter {
199    use super::*;
200
201    pub trait PolarityFilter {
202        fn allow_polarity(&self, p: ClausePolarity) -> bool;
203    }
204    impl PolarityFilter for () {
205        #[inline]
206        fn allow_polarity(&self, _p: ClausePolarity) -> bool {
207            true
208        }
209    }
210    impl PolarityFilter for ClausePolarity {
211        #[inline]
212        fn allow_polarity(&self, p: ClausePolarity) -> bool {
213            *self == p
214        }
215    }
216
217    impl<I, Iter, P, S, T, O> CallerBoundsAccessor<I, Iter, TraitClauses<I, P, S, T, O>>
218    where
219        I: Interner,
220        Iter: Iterator<Item = I::Clause>,
221        P: PolarityFilter,
222        S: SelfTyFilter<I>,
223        T: TraitFilter<I>,
224        O: OutputAs<I>,
225    {
226        #[inline]
227        pub fn with_polarity(
228            self,
229            polarity: ClausePolarity,
230        ) -> CallerBoundsAccessor<I, Iter, TraitClauses<I, ClausePolarity, S, T, O>> {
231            let CallerBoundsAccessor {
232                clauses: iter,
233                clause_filter:
234                    TraitClauses { cx, polarity_filter: _, self_type_filter, trait_filter, output },
235                cx: PhantomData,
236            } = self;
237            CallerBoundsAccessor {
238                clauses: iter,
239                clause_filter: TraitClauses {
240                    cx,
241                    polarity_filter: polarity,
242                    self_type_filter,
243                    trait_filter,
244                    output,
245                },
246                cx: PhantomData,
247            }
248        }
249        #[inline]
250        pub fn validate_self_ty<F: Fn(I::Ty) -> bool>(
251            self,
252            validate_fn: F,
253        ) -> CallerBoundsAccessor<I, Iter, TraitClauses<I, P, FilterFn<F>, T, O>> {
254            let CallerBoundsAccessor {
255                clauses: iter,
256                clause_filter:
257                    TraitClauses { cx, polarity_filter, self_type_filter: _, trait_filter, output },
258                cx: PhantomData,
259            } = self;
260            CallerBoundsAccessor {
261                clauses: iter,
262                clause_filter: TraitClauses {
263                    cx,
264                    polarity_filter,
265                    self_type_filter: FilterFn { f: validate_fn },
266                    trait_filter,
267                    output,
268                },
269                cx: PhantomData,
270            }
271        }
272        #[inline]
273        pub fn with_self_ty(
274            self,
275            desired_self_ty: I::Ty,
276        ) -> CallerBoundsAccessor<I, Iter, TraitClauses<I, P, FilterFn<impl Fn(I::Ty) -> bool>, T, O>>
277        {
278            self.validate_self_ty(move |actual_self_ty| actual_self_ty == desired_self_ty)
279        }
280        #[inline]
281        pub fn for_trait(
282            self,
283            def_id: I::TraitId,
284        ) -> CallerBoundsAccessor<I, Iter, TraitClauses<I, P, S, TraitWithId<I>, O>> {
285            let CallerBoundsAccessor {
286                clauses: iter,
287                clause_filter:
288                    TraitClauses { polarity_filter, self_type_filter, trait_filter: _, output, cx },
289                cx: PhantomData,
290            } = self;
291            CallerBoundsAccessor {
292                clauses: iter,
293                clause_filter: TraitClauses {
294                    polarity_filter,
295                    self_type_filter,
296                    trait_filter: TraitWithId(def_id),
297                    output,
298                    cx,
299                },
300                cx: PhantomData,
301            }
302        }
303        #[inline]
304        pub fn for_trait_lang_item(
305            self,
306            lang_item: SolverTraitLangItem,
307        ) -> CallerBoundsAccessor<I, Iter, TraitClauses<I, P, S, TraitWithId<I>, O>> {
308            let cx = self.clause_filter.cx;
309            self.for_trait(cx.require_trait_lang_item(lang_item))
310        }
311
312        #[inline]
313        pub fn interned(
314            self,
315        ) -> CallerBoundsAccessor<I, Iter, TraitClauses<I, P, S, T, OutputAsInternedClause>>
316        {
317            let CallerBoundsAccessor {
318                clauses: iter,
319                clause_filter:
320                    TraitClauses { cx, polarity_filter, self_type_filter, trait_filter, output: _ },
321                cx: PhantomData,
322            } = self;
323            CallerBoundsAccessor {
324                clauses: iter,
325                clause_filter: TraitClauses {
326                    cx,
327                    polarity_filter,
328                    self_type_filter,
329                    trait_filter,
330                    output: OutputAsInternedClause,
331                },
332                cx: PhantomData,
333            }
334        }
335    }
336}
337
338mod self_ty_filter {
339    use super::*;
340
341    pub trait SelfTyFilter<I>
342    where
343        I: Interner,
344    {
345        fn allow_self_ty(&self, ty: I::Ty) -> bool;
346    }
347
348    impl<I> SelfTyFilter<I> for ()
349    where
350        I: Interner,
351    {
352        #[inline]
353        fn allow_self_ty(&self, _ty: I::Ty) -> bool {
354            true
355        }
356    }
357
358    pub struct FilterFn<F> {
359        pub f: F,
360    }
361    impl<I, F> SelfTyFilter<I> for FilterFn<F>
362    where
363        I: Interner,
364        F: Fn(I::Ty) -> bool,
365    {
366        #[inline]
367        fn allow_self_ty(&self, ty: I::Ty) -> bool {
368            (self.f)(ty)
369        }
370    }
371}
372
373mod trait_filter {
374    use super::*;
375
376    pub trait TraitFilter<I>
377    where
378        I: Interner,
379    {
380        fn allow_clause(&self, clause: TraitClause<I>) -> bool;
381    }
382
383    impl<I> TraitFilter<I> for ()
384    where
385        I: Interner,
386    {
387        #[inline]
388        fn allow_clause(&self, _clause: TraitClause<I>) -> bool {
389            true
390        }
391    }
392
393    pub struct TraitWithId<I>(pub I::TraitId)
394    where
395        I: Interner;
396    impl<I> TraitFilter<I> for TraitWithId<I>
397    where
398        I: Interner,
399    {
400        #[inline]
401        fn allow_clause(&self, clause: TraitClause<I>) -> bool {
402            clause.def_id() == self.0
403        }
404    }
405}
406
407mod output_as {
408    use super::*;
409
410    pub trait OutputAs<I: Interner> {
411        type Output;
412        fn construct_from_trait_clause(tc: Binder<I, TraitClause<I>>, cx: I) -> Self::Output;
413    }
414
415    pub struct OutputAsInternedClause;
416    impl<I: Interner> OutputAs<I> for OutputAsInternedClause {
417        type Output = I::Clause;
418        fn construct_from_trait_clause(tc: Binder<I, TraitClause<I>>, cx: I) -> I::Clause {
419            tc.upcast(cx)
420        }
421    }
422
423    pub struct OutputAsTraitClause;
424    impl<I: Interner> OutputAs<I> for OutputAsTraitClause {
425        type Output = Binder<I, TraitClause<I>>;
426        fn construct_from_trait_clause(
427            tc: Binder<I, TraitClause<I>>,
428            _cx: I,
429        ) -> Binder<I, TraitClause<I>> {
430            tc
431        }
432    }
433}