1 //! This module contains "rote and uninteresting" impls of `Fold` for
2 //! various types. In general, we prefer to derive `Fold`, but
3 //! sometimes that doesn't work for whatever reason.
4 //!
5 //! The more interesting impls of `Fold` remain in the `fold` module.
6 
7 use super::in_place;
8 use crate::*;
9 use std::marker::PhantomData;
10 
11 impl<T: Fold<I>, I: Interner> Fold<I> for Vec<T> {
12     type Result = Vec<T::Result>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,13     fn fold_with<'i>(
14         self,
15         folder: &mut dyn Folder<'i, I>,
16         outer_binder: DebruijnIndex,
17     ) -> Fallible<Self::Result>
18     where
19         I: 'i,
20     {
21         in_place::fallible_map_vec(self, |e| e.fold_with(folder, outer_binder))
22     }
23 }
24 
25 impl<T: Fold<I>, I: Interner> Fold<I> for Box<T> {
26     type Result = Box<T::Result>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,27     fn fold_with<'i>(
28         self,
29         folder: &mut dyn Folder<'i, I>,
30         outer_binder: DebruijnIndex,
31     ) -> Fallible<Self::Result>
32     where
33         I: 'i,
34     {
35         in_place::fallible_map_box(self, |e| e.fold_with(folder, outer_binder))
36     }
37 }
38 
39 macro_rules! tuple_fold {
40     ($($n:ident),*) => {
41         impl<$($n: Fold<I>,)* I: Interner> Fold<I> for ($($n,)*) {
42             type Result = ($($n::Result,)*);
43             fn fold_with<'i>(self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex) -> Fallible<Self::Result>
44             where
45                 I: 'i,
46             {
47                 #[allow(non_snake_case)]
48                 let ($($n),*) = self;
49                 Ok(($($n.fold_with(folder, outer_binder)?,)*))
50             }
51         }
52     }
53 }
54 
55 tuple_fold!(A, B);
56 tuple_fold!(A, B, C);
57 tuple_fold!(A, B, C, D);
58 tuple_fold!(A, B, C, D, E);
59 
60 impl<T: Fold<I>, I: Interner> Fold<I> for Option<T> {
61     type Result = Option<T::Result>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,62     fn fold_with<'i>(
63         self,
64         folder: &mut dyn Folder<'i, I>,
65         outer_binder: DebruijnIndex,
66     ) -> Fallible<Self::Result>
67     where
68         I: 'i,
69     {
70         match self {
71             None => Ok(None),
72             Some(e) => Ok(Some(e.fold_with(folder, outer_binder)?)),
73         }
74     }
75 }
76 
77 impl<I: Interner> Fold<I> for GenericArg<I> {
78     type Result = GenericArg<I>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,79     fn fold_with<'i>(
80         self,
81         folder: &mut dyn Folder<'i, I>,
82         outer_binder: DebruijnIndex,
83     ) -> Fallible<Self::Result>
84     where
85         I: 'i,
86     {
87         let interner = folder.interner();
88 
89         let data = self
90             .data(interner)
91             .clone()
92             .fold_with(folder, outer_binder)?;
93         Ok(GenericArg::new(interner, data))
94     }
95 }
96 
97 impl<I: Interner> Fold<I> for Substitution<I> {
98     type Result = Substitution<I>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,99     fn fold_with<'i>(
100         self,
101         folder: &mut dyn Folder<'i, I>,
102         outer_binder: DebruijnIndex,
103     ) -> Fallible<Self::Result>
104     where
105         I: 'i,
106     {
107         let interner = folder.interner();
108 
109         let folded = self
110             .iter(interner)
111             .cloned()
112             .map(|p| p.fold_with(folder, outer_binder));
113         Ok(Substitution::from_fallible(interner, folded)?)
114     }
115 }
116 
117 impl<I: Interner> Fold<I> for Goals<I> {
118     type Result = Goals<I>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,119     fn fold_with<'i>(
120         self,
121         folder: &mut dyn Folder<'i, I>,
122         outer_binder: DebruijnIndex,
123     ) -> Fallible<Self::Result>
124     where
125         I: 'i,
126     {
127         let interner = folder.interner();
128         let folded = self
129             .iter(interner)
130             .cloned()
131             .map(|p| p.fold_with(folder, outer_binder));
132         Ok(Goals::from_fallible(interner, folded)?)
133     }
134 }
135 
136 impl<I: Interner> Fold<I> for ProgramClauses<I> {
137     type Result = ProgramClauses<I>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,138     fn fold_with<'i>(
139         self,
140         folder: &mut dyn Folder<'i, I>,
141         outer_binder: DebruijnIndex,
142     ) -> Fallible<Self::Result>
143     where
144         I: 'i,
145     {
146         let interner = folder.interner();
147         let folded = self
148             .iter(interner)
149             .cloned()
150             .map(|p| p.fold_with(folder, outer_binder));
151         Ok(ProgramClauses::from_fallible(interner, folded)?)
152     }
153 }
154 
155 impl<I: Interner> Fold<I> for QuantifiedWhereClauses<I> {
156     type Result = QuantifiedWhereClauses<I>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,157     fn fold_with<'i>(
158         self,
159         folder: &mut dyn Folder<'i, I>,
160         outer_binder: DebruijnIndex,
161     ) -> Fallible<Self::Result>
162     where
163         I: 'i,
164     {
165         let interner = folder.interner();
166         let folded = self
167             .iter(interner)
168             .cloned()
169             .map(|p| p.fold_with(folder, outer_binder));
170         Ok(QuantifiedWhereClauses::from_fallible(interner, folded)?)
171     }
172 }
173 
174 impl<I: Interner> Fold<I> for Constraints<I> {
175     type Result = Constraints<I>;
fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> Fallible<Self::Result> where I: 'i,176     fn fold_with<'i>(
177         self,
178         folder: &mut dyn Folder<'i, I>,
179         outer_binder: DebruijnIndex,
180     ) -> Fallible<Self::Result>
181     where
182         I: 'i,
183     {
184         let interner = folder.interner();
185         let folded = self
186             .iter(interner)
187             .cloned()
188             .map(|p| p.fold_with(folder, outer_binder));
189         Ok(Constraints::from_fallible(interner, folded)?)
190     }
191 }
192 
193 #[doc(hidden)]
194 #[macro_export]
195 macro_rules! copy_fold {
196     ($t:ty) => {
197         impl<I: Interner> $crate::fold::Fold<I> for $t {
198             type Result = Self;
199             fn fold_with<'i>(
200                 self,
201                 _folder: &mut dyn ($crate::fold::Folder<'i, I>),
202                 _outer_binder: DebruijnIndex,
203             ) -> ::chalk_ir::Fallible<Self::Result>
204             where
205                 I: 'i,
206             {
207                 Ok(self)
208             }
209         }
210     };
211 }
212 
213 copy_fold!(bool);
214 copy_fold!(usize);
215 copy_fold!(UniverseIndex);
216 copy_fold!(PlaceholderIndex);
217 copy_fold!(QuantifierKind);
218 copy_fold!(DebruijnIndex);
219 copy_fold!(());
220 copy_fold!(UintTy);
221 copy_fold!(IntTy);
222 copy_fold!(FloatTy);
223 copy_fold!(Scalar);
224 copy_fold!(ClausePriority);
225 copy_fold!(Mutability);
226 copy_fold!(Safety);
227 
228 #[doc(hidden)]
229 #[macro_export]
230 macro_rules! id_fold {
231     ($t:ident) => {
232         impl<I: Interner> $crate::fold::Fold<I> for $t<I> {
233             type Result = $t<I>;
234             fn fold_with<'i>(
235                 self,
236                 _folder: &mut dyn ($crate::fold::Folder<'i, I>),
237                 _outer_binder: DebruijnIndex,
238             ) -> ::chalk_ir::Fallible<Self::Result>
239             where
240                 I: 'i,
241             {
242                 Ok(self)
243             }
244         }
245     };
246 }
247 
248 id_fold!(ImplId);
249 id_fold!(AdtId);
250 id_fold!(TraitId);
251 id_fold!(AssocTypeId);
252 id_fold!(OpaqueTyId);
253 id_fold!(FnDefId);
254 id_fold!(ClosureId);
255 id_fold!(GeneratorId);
256 id_fold!(ForeignDefId);
257 
258 impl<I: Interner> SuperFold<I> for ProgramClauseData<I> {
super_fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> ::chalk_ir::Fallible<Self::Result> where I: 'i,259     fn super_fold_with<'i>(
260         self,
261         folder: &mut dyn Folder<'i, I>,
262         outer_binder: DebruijnIndex,
263     ) -> ::chalk_ir::Fallible<Self::Result>
264     where
265         I: 'i,
266     {
267         Ok(ProgramClauseData(self.0.fold_with(folder, outer_binder)?))
268     }
269 }
270 
271 impl<I: Interner> SuperFold<I> for ProgramClause<I> {
super_fold_with<'i>( self, folder: &mut dyn Folder<'i, I>, outer_binder: DebruijnIndex, ) -> ::chalk_ir::Fallible<Self::Result> where I: 'i,272     fn super_fold_with<'i>(
273         self,
274         folder: &mut dyn Folder<'i, I>,
275         outer_binder: DebruijnIndex,
276     ) -> ::chalk_ir::Fallible<Self::Result>
277     where
278         I: 'i,
279     {
280         let clause = self.data(folder.interner()).clone();
281         Ok(clause
282             .super_fold_with(folder, outer_binder)?
283             .intern(folder.interner()))
284     }
285 }
286 
287 impl<I: Interner> Fold<I> for PhantomData<I> {
288     type Result = PhantomData<I>;
289 
fold_with<'i>( self, _folder: &mut dyn Folder<'i, I>, _outer_binder: DebruijnIndex, ) -> ::chalk_ir::Fallible<Self::Result> where I: 'i,290     fn fold_with<'i>(
291         self,
292         _folder: &mut dyn Folder<'i, I>,
293         _outer_binder: DebruijnIndex,
294     ) -> ::chalk_ir::Fallible<Self::Result>
295     where
296         I: 'i,
297     {
298         Ok(PhantomData)
299     }
300 }
301