1use crate::ast::*;
2use derive_generic_visitor::*;
3use std::borrow::Cow;
4use std::convert::Infallible;
5use std::fmt::Debug;
6use std::iter::Iterator;
7
8pub trait VarsVisitor {
13 fn visit_erased_region(&mut self) -> Option<Region> {
14 None
15 }
16 fn visit_region_var(&mut self, _v: RegionDbVar) -> Option<Region> {
17 None
18 }
19 fn visit_type_var(&mut self, _v: TypeDbVar) -> Option<Ty> {
20 None
21 }
22 fn visit_const_generic_var(&mut self, _v: ConstGenericDbVar) -> Option<ConstantExprKind> {
23 None
24 }
25 fn visit_clause_var(&mut self, _v: ClauseDbVar) -> Option<TraitRefKind> {
26 None
27 }
28 fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
29 None
30 }
31 fn visit_metadata_value(&mut self, _value: &MetadataValue) {}
32}
33
34#[derive(Visitor)]
37pub(crate) struct SubstVisitor<'a> {
38 generics: &'a GenericArgs,
39 self_ref: Option<&'a TraitRefKind>,
40 explicits_only: bool,
42 had_error: bool,
43}
44impl<'a> SubstVisitor<'a> {
45 pub(crate) fn new(
46 generics: &'a GenericArgs,
47 self_ref: Option<&'a TraitRefKind>,
48 explicits_only: bool,
49 ) -> Self {
50 Self {
51 generics,
52 self_ref,
53 explicits_only,
54 had_error: false,
55 }
56 }
57
58 pub fn visit<T: TyVisitable>(mut self, mut x: T) -> Result<T, GenericsMismatch> {
59 x.visit_vars(&mut self);
60 if self.had_error {
61 Err(GenericsMismatch)
62 } else {
63 Ok(x)
64 }
65 }
66
67 fn process_var<Id, T>(
69 &mut self,
70 var: DeBruijnVar<Id>,
71 get: impl Fn(Id) -> Option<&'a T>,
72 ) -> Option<T>
73 where
74 Id: Copy,
75 T: Clone + TyVisitable,
76 DeBruijnVar<Id>: Into<T>,
77 {
78 match var {
79 DeBruijnVar::Bound(dbid, varid) => {
80 Some(if let Some(dbid) = dbid.sub(DeBruijnId::one()) {
81 DeBruijnVar::Bound(dbid, varid).into()
83 } else {
84 match get(varid) {
85 Some(v) => v.clone(),
86 None => {
87 self.had_error = true;
88 return None;
89 }
90 }
91 })
92 }
93 DeBruijnVar::Free(..) => None,
94 }
95 }
96}
97impl VarsVisitor for SubstVisitor<'_> {
98 fn visit_region_var(&mut self, v: RegionDbVar) -> Option<Region> {
99 self.process_var(v, |id| self.generics.regions.get(id))
100 }
101 fn visit_type_var(&mut self, v: TypeDbVar) -> Option<Ty> {
102 self.process_var(v, |id| self.generics.types.get(id))
103 }
104 fn visit_const_generic_var(&mut self, v: ConstGenericDbVar) -> Option<ConstantExprKind> {
105 self.process_var(v, |id| {
106 self.generics.const_generics.get(id).map(|c| c.kind())
107 })
108 }
109 fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
110 if self.explicits_only {
111 None
112 } else {
113 self.process_var(v, |id| Some(&self.generics.trait_refs.get(id)?.kind))
114 }
115 }
116 fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
117 Some(self.self_ref.cloned().expect(
118 "used `substitute` on an item coming from a trait; \
119 use `substitute_with_self` or `substitute_inner_binder` instead.",
120 ))
121 }
122 fn visit_metadata_value(&mut self, _value: &MetadataValue) {
123 self.had_error = true;
124 }
125}
126
127#[derive(Debug)]
128pub struct GenericsMismatch;
129
130pub trait TyVisitable: Sized + AstVisitable {
132 fn visit_vars(&mut self, v: &mut impl VarsVisitor) {
136 #[derive(Visitor)]
137 struct Wrap<'v, V> {
138 v: &'v mut V,
139 depth: DeBruijnId,
140 }
141 impl<V> VisitorWithBinderDepth for Wrap<'_, V> {
142 fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
143 &mut self.depth
144 }
145 }
146 impl<V: VarsVisitor> VisitAstMut for Wrap<'_, V> {
147 fn visit<T: AstVisitable>(&mut self, x: &mut T) -> ControlFlow<Self::Break> {
148 VisitWithBinderDepth::new(self).visit(x)
149 }
150
151 fn exit_region(&mut self, r: &mut Region) {
152 match r {
153 Region::Var(var)
154 if let Some(var) = var.move_out_from_depth(self.depth)
155 && let Some(new_r) = self.v.visit_region_var(var) =>
156 {
157 *r = new_r.move_under_binders(self.depth);
158 }
159 Region::Erased | Region::Body(..)
160 if let Some(new_r) = self.v.visit_erased_region() =>
161 {
162 *r = new_r.move_under_binders(self.depth);
163 }
164 _ => (),
165 }
166 }
167 fn exit_ty(&mut self, ty: &mut Ty) {
168 if let TyKind::TypeVar(var) = ty.kind()
169 && let Some(var) = var.move_out_from_depth(self.depth)
170 && let Some(new_ty) = self.v.visit_type_var(var)
171 {
172 *ty = new_ty.move_under_binders(self.depth);
173 }
174 }
175 fn exit_constant_expr_kind(&mut self, kind: &mut ConstantExprKind) {
176 if let ConstantExprKind::Var(var) = kind
177 && let Some(var) = var.move_out_from_depth(self.depth)
178 && let Some(new_cg) = self.v.visit_const_generic_var(var)
179 {
180 *kind = new_cg.move_under_binders(self.depth);
181 }
182 }
183 fn exit_trait_ref_kind(&mut self, kind: &mut TraitRefKind) {
184 match kind {
185 TraitRefKind::SelfId => {
186 if let Some(new_kind) = self.v.visit_self_clause() {
187 *kind = new_kind.move_under_binders(self.depth);
188 }
189 }
190 TraitRefKind::Clause(var) => {
191 if let Some(var) = var.move_out_from_depth(self.depth)
192 && let Some(new_kind) = self.v.visit_clause_var(var)
193 {
194 *kind = new_kind.move_under_binders(self.depth);
195 }
196 }
197 _ => {}
198 }
199 }
200 fn enter_metadata_value(&mut self, value: &mut MetadataValue) {
201 self.v.visit_metadata_value(value);
202 }
203 }
204 Wrap {
205 v,
206 depth: DeBruijnId::zero(),
207 }
208 .visit(self);
209 }
210
211 fn substitute(self, generics: &GenericArgs) -> Self {
215 SubstVisitor::new(generics, None, false)
216 .visit(self)
217 .unwrap()
218 }
219 fn substitute_inner_binder(self, generics: &GenericArgs) -> Self {
222 self.substitute_with_self(generics, &TraitRefKind::SelfId)
223 }
224 fn substitute_explicits(self, generics: &GenericArgs) -> Self {
226 SubstVisitor::new(generics, None, true).visit(self).unwrap()
227 }
228 fn substitute_with_self(self, generics: &GenericArgs, self_ref: &TraitRefKind) -> Self {
230 self.try_substitute_with_self(generics, self_ref).unwrap()
231 }
232 fn substitute_with_tref(self, tref: &TraitRef) -> Self {
234 let pred = tref.trait_decl_ref.clone().erase();
235 self.substitute_with_self(&pred.generics, &tref.kind)
236 }
237 fn try_substitute_with_tref(self, tref: &TraitRef) -> Result<Self, GenericsMismatch> {
239 let pred = tref.trait_decl_ref.clone().erase();
240 self.try_substitute_with_self(&pred.generics, &tref.kind)
241 }
242
243 fn try_substitute(self, generics: &GenericArgs) -> Result<Self, GenericsMismatch> {
244 SubstVisitor::new(generics, None, false).visit(self)
245 }
246 fn try_substitute_with_self(
247 self,
248 generics: &GenericArgs,
249 self_ref: &TraitRefKind,
250 ) -> Result<Self, GenericsMismatch> {
251 SubstVisitor::new(generics, Some(self_ref), false).visit(self)
252 }
253
254 fn move_under_binder(self) -> Self {
256 self.move_under_binders(DeBruijnId::one())
257 }
258
259 fn move_under_binders(mut self, depth: DeBruijnId) -> Self {
261 if !depth.is_zero() {
262 let Continue(()) = self.visit_db_id::<Infallible>(|id| {
263 *id = id.plus(depth);
264 Continue(())
265 });
266 }
267 self
268 }
269
270 fn move_from_under_binder(self) -> Option<Self> {
272 self.move_from_under_binders(DeBruijnId::one())
273 }
274
275 fn move_from_under_binders(mut self, depth: DeBruijnId) -> Option<Self> {
278 self.visit_db_id::<()>(|id| match id.sub(depth) {
279 Some(sub) => {
280 *id = sub;
281 Continue(())
282 }
283 None => Break(()),
284 })
285 .is_continue()
286 .then_some(self)
287 }
288
289 fn visit_db_id<B>(
293 &mut self,
294 f: impl FnMut(&mut DeBruijnId) -> ControlFlow<B>,
295 ) -> ControlFlow<B> {
296 struct Wrap<F> {
297 f: F,
298 depth: DeBruijnId,
299 }
300 impl<B, F> Visitor for Wrap<F>
301 where
302 F: FnMut(&mut DeBruijnId) -> ControlFlow<B>,
303 {
304 type Break = B;
305 }
306 impl<B, F> VisitAstMut for Wrap<F>
307 where
308 F: FnMut(&mut DeBruijnId) -> ControlFlow<B>,
309 {
310 fn enter_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
311 self.depth = self.depth.incr()
312 }
313 fn exit_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
314 self.depth = self.depth.decr()
315 }
316 fn enter_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
317 self.depth = self.depth.incr()
318 }
319 fn exit_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
320 self.depth = self.depth.decr()
321 }
322
323 fn visit_de_bruijn_id(&mut self, x: &mut DeBruijnId) -> ControlFlow<Self::Break> {
324 if let Some(mut shifted) = x.sub(self.depth) {
325 (self.f)(&mut shifted)?;
326 *x = shifted.plus(self.depth)
327 }
328 Continue(())
329 }
330 }
331 self.drive_mut(&mut Wrap {
332 f,
333 depth: DeBruijnId::zero(),
334 })
335 }
336
337 fn replace_erased_regions(mut self, f: impl FnMut() -> Region) -> Self {
340 #[derive(Visitor)]
341 struct RefreshErasedRegions<F>(F);
342 impl<F: FnMut() -> Region> VarsVisitor for RefreshErasedRegions<F> {
343 fn visit_erased_region(&mut self) -> Option<Region> {
344 Some((self.0)())
345 }
346 }
347 self.visit_vars(&mut RefreshErasedRegions(f));
348 self
349 }
350}
351
352impl<T: AstVisitable> TyVisitable for T {}
353
354#[derive(Debug, Clone)]
357pub struct Substituted<'a, T> {
358 pub val: &'a T,
359 pub generics: Cow<'a, GenericArgs>,
360 pub trait_self: Option<&'a TraitRefKind>,
361}
362
363impl<'a, T> Substituted<'a, T> {
364 pub fn new(val: &'a T, generics: &'a GenericArgs) -> Self {
365 Self {
366 val,
367 generics: Cow::Borrowed(generics),
368 trait_self: None,
369 }
370 }
371 pub fn new_for_trait(
372 val: &'a T,
373 generics: &'a GenericArgs,
374 trait_self: &'a TraitRefKind,
375 ) -> Self {
376 Self {
377 val,
378 generics: Cow::Borrowed(generics),
379 trait_self: Some(trait_self),
380 }
381 }
382 pub fn new_for_trait_ref(val: &'a T, tref: &'a TraitRef) -> Self {
383 Self {
384 val,
385 generics: Cow::Owned(*tref.trait_decl_ref.clone().erase().generics),
386 trait_self: Some(&tref.kind),
387 }
388 }
389
390 pub fn rebind<U>(&self, val: &'a U) -> Substituted<'a, U> {
391 Substituted {
392 val,
393 generics: self.generics.clone(),
394 trait_self: self.trait_self,
395 }
396 }
397
398 pub fn substitute(&self) -> T
399 where
400 T: TyVisitable + Clone,
401 {
402 self.try_substitute().unwrap()
403 }
404 pub fn try_substitute(&self) -> Result<T, GenericsMismatch>
405 where
406 T: TyVisitable + Clone,
407 {
408 match self.trait_self {
409 None => self.val.clone().try_substitute(&self.generics),
410 Some(trait_self) => self
411 .val
412 .clone()
413 .try_substitute_with_self(&self.generics, trait_self),
414 }
415 }
416
417 pub fn iter<Item: 'a>(&self) -> impl Iterator<Item = Substituted<'a, Item>>
418 where
419 &'a T: IntoIterator<Item = &'a Item>,
420 {
421 self.val.into_iter().map(move |x| self.rebind(x))
422 }
423}
424
425#[derive(Debug, Clone, Copy)]
431pub struct ItemBinder<ItemId, T> {
432 pub item_id: ItemId,
433 val: T,
434}
435
436impl<ItemId, T> ItemBinder<ItemId, T>
437where
438 ItemId: Debug + Copy + PartialEq,
439{
440 pub fn new(item_id: ItemId, val: T) -> Self {
441 Self { item_id, val }
442 }
443
444 pub fn as_ref(&self) -> ItemBinder<ItemId, &T> {
445 ItemBinder {
446 item_id: self.item_id,
447 val: &self.val,
448 }
449 }
450
451 pub fn map_bound<U>(self, f: impl FnOnce(T) -> U) -> ItemBinder<ItemId, U> {
452 ItemBinder {
453 item_id: self.item_id,
454 val: f(self.val),
455 }
456 }
457
458 fn assert_item_id(&self, item_id: ItemId) {
459 assert_eq!(
460 self.item_id, item_id,
461 "Trying to use item bound for {:?} as if it belonged to {:?}",
462 self.item_id, item_id
463 );
464 }
465
466 pub fn under_binder_of(self, item_id: ItemId) -> T {
469 self.assert_item_id(item_id);
470 self.val
471 }
472
473 pub fn substitute<OtherItem: Debug + Copy + PartialEq>(
477 self,
478 args: ItemBinder<OtherItem, &GenericArgs>,
479 ) -> ItemBinder<OtherItem, T>
480 where
481 ItemId: Into<ItemId>,
482 T: TyVisitable,
483 {
484 args.map_bound(|args| self.val.substitute(args))
485 }
486}
487
488#[derive(Debug, Clone, Copy, PartialEq, Eq)]
490pub struct CurrentItem;
491
492impl<T> ItemBinder<CurrentItem, T> {
493 pub fn under_current_binder(self) -> T {
494 self.val
495 }
496}