]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_traits/src/chalk/lowering.rs
Auto merge of #98627 - RalfJung:interpret-arith, r=lcnr
[rust.git] / compiler / rustc_traits / src / chalk / lowering.rs
1 //! Contains the logic to lower rustc types into Chalk types
2 //!
3 //! In many cases there is a 1:1 relationship between a rustc type and a Chalk type.
4 //! For example, a `SubstsRef` maps almost directly to a `Substitution`. In some
5 //! other cases, such as `Param`s, there is no Chalk type, so we have to handle
6 //! accordingly.
7 //!
8 //! ## `Ty` lowering
9 //! Much of the `Ty` lowering is 1:1 with Chalk. (Or will be eventually). A
10 //! helpful table for what types lower to what can be found in the
11 //! [Chalk book](https://rust-lang.github.io/chalk/book/types/rust_types.html).
12 //! The most notable difference lies with `Param`s. To convert from rustc to
13 //! Chalk, we eagerly and deeply convert `Param`s to placeholders (in goals) or
14 //! bound variables (for clause generation through functions in `db`).
15 //!
16 //! ## `Region` lowering
17 //! Regions are handled in rustc and Chalk is quite differently. In rustc, there
18 //! is a difference between "early bound" and "late bound" regions, where only
19 //! the late bound regions have a `DebruijnIndex`. Moreover, in Chalk all
20 //! regions (Lifetimes) have an associated index. In rustc, only `BrAnon`s have
21 //! an index, whereas `BrNamed` don't. In order to lower regions to Chalk, we
22 //! convert all regions into `BrAnon` late-bound regions.
23 //!
24 //! ## `Const` lowering
25 //! Chalk doesn't handle consts currently, so consts are currently lowered to
26 //! an empty tuple.
27 //!
28 //! ## Bound variable collection
29 //! Another difference between rustc and Chalk lies in the handling of binders.
30 //! Chalk requires that we store the bound parameter kinds, whereas rustc does
31 //! not. To lower anything wrapped in a `Binder`, we first deeply find any bound
32 //! variables from the current `Binder`.
33
34 use rustc_ast::ast;
35 use rustc_middle::traits::{ChalkEnvironmentAndGoal, ChalkRustInterner as RustInterner};
36 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
37 use rustc_middle::ty::{
38     self, Binder, Region, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitor,
39 };
40 use rustc_span::def_id::DefId;
41
42 use chalk_ir::{FnSig, ForeignDefId};
43 use rustc_hir::Unsafety;
44 use std::collections::btree_map::{BTreeMap, Entry};
45 use std::ops::ControlFlow;
46
47 /// Essentially an `Into` with a `&RustInterner` parameter
48 pub(crate) trait LowerInto<'tcx, T> {
49     /// Lower a rustc construct (e.g., `ty::TraitPredicate`) to a chalk type, consuming `self`.
50     fn lower_into(self, interner: RustInterner<'tcx>) -> T;
51 }
52
53 impl<'tcx> LowerInto<'tcx, chalk_ir::Substitution<RustInterner<'tcx>>> for SubstsRef<'tcx> {
54     fn lower_into(
55         self,
56         interner: RustInterner<'tcx>,
57     ) -> chalk_ir::Substitution<RustInterner<'tcx>> {
58         chalk_ir::Substitution::from_iter(interner, self.iter().map(|s| s.lower_into(interner)))
59     }
60 }
61
62 impl<'tcx> LowerInto<'tcx, SubstsRef<'tcx>> for &chalk_ir::Substitution<RustInterner<'tcx>> {
63     fn lower_into(self, interner: RustInterner<'tcx>) -> SubstsRef<'tcx> {
64         interner.tcx.mk_substs(self.iter(interner).map(|subst| subst.lower_into(interner)))
65     }
66 }
67
68 impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy<RustInterner<'tcx>>> for ty::ProjectionTy<'tcx> {
69     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasTy<RustInterner<'tcx>> {
70         chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
71             associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id),
72             substitution: self.substs.lower_into(interner),
73         })
74     }
75 }
76
77 impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>>>
78     for ChalkEnvironmentAndGoal<'tcx>
79 {
80     fn lower_into(
81         self,
82         interner: RustInterner<'tcx>,
83     ) -> chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>> {
84         let clauses = self.environment.into_iter().map(|predicate| {
85             let (predicate, binders, _named_regions) =
86                 collect_bound_vars(interner, interner.tcx, predicate.kind());
87             let consequence = match predicate {
88                 ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
89                     chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner)))
90                 }
91                 ty::PredicateKind::Trait(predicate) => chalk_ir::DomainGoal::FromEnv(
92                     chalk_ir::FromEnv::Trait(predicate.trait_ref.lower_into(interner)),
93                 ),
94                 ty::PredicateKind::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
95                     chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
96                         a: predicate.0.lower_into(interner),
97                         b: predicate.1.lower_into(interner),
98                     }),
99                 ),
100                 ty::PredicateKind::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
101                     chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
102                         ty: predicate.0.lower_into(interner),
103                         lifetime: predicate.1.lower_into(interner),
104                     }),
105                 ),
106                 ty::PredicateKind::Projection(predicate) => chalk_ir::DomainGoal::Holds(
107                     chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
108                 ),
109                 ty::PredicateKind::WellFormed(arg) => match arg.unpack() {
110                     ty::GenericArgKind::Type(ty) => chalk_ir::DomainGoal::WellFormed(
111                         chalk_ir::WellFormed::Ty(ty.lower_into(interner)),
112                     ),
113                     // FIXME(chalk): we need to change `WellFormed` in Chalk to take a `GenericArg`
114                     _ => chalk_ir::DomainGoal::WellFormed(chalk_ir::WellFormed::Ty(
115                         interner.tcx.types.unit.lower_into(interner),
116                     )),
117                 },
118                 ty::PredicateKind::ObjectSafe(..)
119                 | ty::PredicateKind::ClosureKind(..)
120                 | ty::PredicateKind::Subtype(..)
121                 | ty::PredicateKind::Coerce(..)
122                 | ty::PredicateKind::ConstEvaluatable(..)
123                 | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
124             };
125             let value = chalk_ir::ProgramClauseImplication {
126                 consequence,
127                 conditions: chalk_ir::Goals::empty(interner),
128                 priority: chalk_ir::ClausePriority::High,
129                 constraints: chalk_ir::Constraints::empty(interner),
130             };
131             chalk_ir::ProgramClauseData(chalk_ir::Binders::new(binders, value)).intern(interner)
132         });
133
134         let goal: chalk_ir::GoalData<RustInterner<'tcx>> = self.goal.lower_into(interner);
135         chalk_ir::InEnvironment {
136             environment: chalk_ir::Environment {
137                 clauses: chalk_ir::ProgramClauses::from_iter(interner, clauses),
138             },
139             goal: goal.intern(interner),
140         }
141     }
142 }
143
144 impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predicate<'tcx> {
145     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GoalData<RustInterner<'tcx>> {
146         let (predicate, binders, _named_regions) =
147             collect_bound_vars(interner, interner.tcx, self.kind());
148
149         let value = match predicate {
150             ty::PredicateKind::Trait(predicate) => {
151                 chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
152                     chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)),
153                 ))
154             }
155             ty::PredicateKind::RegionOutlives(predicate) => {
156                 chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
157                     chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
158                         a: predicate.0.lower_into(interner),
159                         b: predicate.1.lower_into(interner),
160                     }),
161                 ))
162             }
163             ty::PredicateKind::TypeOutlives(predicate) => {
164                 chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
165                     chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
166                         ty: predicate.0.lower_into(interner),
167                         lifetime: predicate.1.lower_into(interner),
168                     }),
169                 ))
170             }
171             ty::PredicateKind::Projection(predicate) => {
172                 chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
173                     chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
174                 ))
175             }
176             ty::PredicateKind::WellFormed(arg) => match arg.unpack() {
177                 GenericArgKind::Type(ty) => match ty.kind() {
178                     // FIXME(chalk): In Chalk, a placeholder is WellFormed if it
179                     // `FromEnv`. However, when we "lower" Params, we don't update
180                     // the environment.
181                     ty::Placeholder(..) => {
182                         chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
183                     }
184
185                     _ => chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::WellFormed(
186                         chalk_ir::WellFormed::Ty(ty.lower_into(interner)),
187                     )),
188                 },
189                 // FIXME(chalk): handle well formed consts
190                 GenericArgKind::Const(..) => {
191                     chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
192                 }
193                 GenericArgKind::Lifetime(lt) => bug!("unexpect well formed predicate: {:?}", lt),
194             },
195
196             ty::PredicateKind::ObjectSafe(t) => chalk_ir::GoalData::DomainGoal(
197                 chalk_ir::DomainGoal::ObjectSafe(chalk_ir::TraitId(t)),
198             ),
199
200             ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
201                 chalk_ir::GoalData::SubtypeGoal(chalk_ir::SubtypeGoal {
202                     a: a.lower_into(interner),
203                     b: b.lower_into(interner),
204                 })
205             }
206
207             // FIXME(chalk): other predicates
208             //
209             // We can defer this, but ultimately we'll want to express
210             // some of these in terms of chalk operations.
211             ty::PredicateKind::ClosureKind(..)
212             | ty::PredicateKind::Coerce(..)
213             | ty::PredicateKind::ConstEvaluatable(..)
214             | ty::PredicateKind::ConstEquate(..) => {
215                 chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
216             }
217             ty::PredicateKind::TypeWellFormedFromEnv(ty) => chalk_ir::GoalData::DomainGoal(
218                 chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner))),
219             ),
220         };
221
222         chalk_ir::GoalData::Quantified(
223             chalk_ir::QuantifierKind::ForAll,
224             chalk_ir::Binders::new(binders, value.intern(interner)),
225         )
226     }
227 }
228
229 impl<'tcx> LowerInto<'tcx, chalk_ir::TraitRef<RustInterner<'tcx>>>
230     for rustc_middle::ty::TraitRef<'tcx>
231 {
232     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::TraitRef<RustInterner<'tcx>> {
233         chalk_ir::TraitRef {
234             trait_id: chalk_ir::TraitId(self.def_id),
235             substitution: self.substs.lower_into(interner),
236         }
237     }
238 }
239
240 impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq<RustInterner<'tcx>>>
241     for rustc_middle::ty::ProjectionPredicate<'tcx>
242 {
243     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq<RustInterner<'tcx>> {
244         // FIXME(associated_const_equality): teach chalk about terms for alias eq.
245         chalk_ir::AliasEq {
246             ty: self.term.ty().unwrap().lower_into(interner),
247             alias: self.projection_ty.lower_into(interner),
248         }
249     }
250 }
251
252 /*
253 // FIXME(...): Where do I add this to Chalk? I can't find it in the rustc repo anywhere.
254 impl<'tcx> LowerInto<'tcx, chalk_ir::Term<RustInterner<'tcx>>> for rustc_middle::ty::Term<'tcx> {
255   fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Term<RustInterner<'tcx>> {
256     match self {
257       ty::Term::Ty(ty) => ty.lower_into(interner).into(),
258       ty::Term::Const(c) => c.lower_into(interner).into(),
259     }
260   }
261 }
262 */
263
264 impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
265     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Ty<RustInterner<'tcx>> {
266         let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i));
267         let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i));
268         let float = |f| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Float(f));
269
270         match *self.kind() {
271             ty::Bool => chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Bool),
272             ty::Char => chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Char),
273             ty::Int(ty) => match ty {
274                 ty::IntTy::Isize => int(chalk_ir::IntTy::Isize),
275                 ty::IntTy::I8 => int(chalk_ir::IntTy::I8),
276                 ty::IntTy::I16 => int(chalk_ir::IntTy::I16),
277                 ty::IntTy::I32 => int(chalk_ir::IntTy::I32),
278                 ty::IntTy::I64 => int(chalk_ir::IntTy::I64),
279                 ty::IntTy::I128 => int(chalk_ir::IntTy::I128),
280             },
281             ty::Uint(ty) => match ty {
282                 ty::UintTy::Usize => uint(chalk_ir::UintTy::Usize),
283                 ty::UintTy::U8 => uint(chalk_ir::UintTy::U8),
284                 ty::UintTy::U16 => uint(chalk_ir::UintTy::U16),
285                 ty::UintTy::U32 => uint(chalk_ir::UintTy::U32),
286                 ty::UintTy::U64 => uint(chalk_ir::UintTy::U64),
287                 ty::UintTy::U128 => uint(chalk_ir::UintTy::U128),
288             },
289             ty::Float(ty) => match ty {
290                 ty::FloatTy::F32 => float(chalk_ir::FloatTy::F32),
291                 ty::FloatTy::F64 => float(chalk_ir::FloatTy::F64),
292             },
293             ty::Adt(def, substs) => {
294                 chalk_ir::TyKind::Adt(chalk_ir::AdtId(def), substs.lower_into(interner))
295             }
296             ty::Foreign(def_id) => chalk_ir::TyKind::Foreign(ForeignDefId(def_id)),
297             ty::Str => chalk_ir::TyKind::Str,
298             ty::Array(ty, len) => {
299                 chalk_ir::TyKind::Array(ty.lower_into(interner), len.lower_into(interner))
300             }
301             ty::Slice(ty) => chalk_ir::TyKind::Slice(ty.lower_into(interner)),
302
303             ty::RawPtr(ptr) => {
304                 chalk_ir::TyKind::Raw(ptr.mutbl.lower_into(interner), ptr.ty.lower_into(interner))
305             }
306             ty::Ref(region, ty, mutability) => chalk_ir::TyKind::Ref(
307                 mutability.lower_into(interner),
308                 region.lower_into(interner),
309                 ty.lower_into(interner),
310             ),
311             ty::FnDef(def_id, substs) => {
312                 chalk_ir::TyKind::FnDef(chalk_ir::FnDefId(def_id), substs.lower_into(interner))
313             }
314             ty::FnPtr(sig) => {
315                 let (inputs_and_outputs, binders, _named_regions) =
316                     collect_bound_vars(interner, interner.tcx, sig.inputs_and_output());
317                 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
318                     num_binders: binders.len(interner),
319                     sig: sig.lower_into(interner),
320                     substitution: chalk_ir::FnSubst(chalk_ir::Substitution::from_iter(
321                         interner,
322                         inputs_and_outputs.iter().map(|ty| {
323                             chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner)
324                         }),
325                     )),
326                 })
327             }
328             ty::Dynamic(predicates, region) => chalk_ir::TyKind::Dyn(chalk_ir::DynTy {
329                 bounds: predicates.lower_into(interner),
330                 lifetime: region.lower_into(interner),
331             }),
332             ty::Closure(def_id, substs) => {
333                 chalk_ir::TyKind::Closure(chalk_ir::ClosureId(def_id), substs.lower_into(interner))
334             }
335             ty::Generator(def_id, substs, _) => chalk_ir::TyKind::Generator(
336                 chalk_ir::GeneratorId(def_id),
337                 substs.lower_into(interner),
338             ),
339             ty::GeneratorWitness(_) => unimplemented!(),
340             ty::Never => chalk_ir::TyKind::Never,
341             ty::Tuple(types) => {
342                 chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner))
343             }
344             ty::Projection(proj) => chalk_ir::TyKind::Alias(proj.lower_into(interner)),
345             ty::Opaque(def_id, substs) => {
346                 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
347                     opaque_ty_id: chalk_ir::OpaqueTyId(def_id),
348                     substitution: substs.lower_into(interner),
349                 }))
350             }
351             // This should have been done eagerly prior to this, and all Params
352             // should have been substituted to placeholders
353             ty::Param(_) => panic!("Lowering Param when not expected."),
354             ty::Bound(db, bound) => chalk_ir::TyKind::BoundVar(chalk_ir::BoundVar::new(
355                 chalk_ir::DebruijnIndex::new(db.as_u32()),
356                 bound.var.index(),
357             )),
358             ty::Placeholder(_placeholder) => {
359                 chalk_ir::TyKind::Placeholder(chalk_ir::PlaceholderIndex {
360                     ui: chalk_ir::UniverseIndex { counter: _placeholder.universe.as_usize() },
361                     idx: _placeholder.name.as_usize(),
362                 })
363             }
364             ty::Infer(_infer) => unimplemented!(),
365             ty::Error(_) => chalk_ir::TyKind::Error,
366         }
367         .intern(interner)
368     }
369 }
370
371 impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
372     fn lower_into(self, interner: RustInterner<'tcx>) -> Ty<'tcx> {
373         use chalk_ir::TyKind;
374
375         let kind = match self.kind(interner) {
376             TyKind::Adt(struct_id, substitution) => {
377                 ty::Adt(struct_id.0, substitution.lower_into(interner))
378             }
379             TyKind::Scalar(scalar) => match scalar {
380                 chalk_ir::Scalar::Bool => ty::Bool,
381                 chalk_ir::Scalar::Char => ty::Char,
382                 chalk_ir::Scalar::Int(int_ty) => match int_ty {
383                     chalk_ir::IntTy::Isize => ty::Int(ty::IntTy::Isize),
384                     chalk_ir::IntTy::I8 => ty::Int(ty::IntTy::I8),
385                     chalk_ir::IntTy::I16 => ty::Int(ty::IntTy::I16),
386                     chalk_ir::IntTy::I32 => ty::Int(ty::IntTy::I32),
387                     chalk_ir::IntTy::I64 => ty::Int(ty::IntTy::I64),
388                     chalk_ir::IntTy::I128 => ty::Int(ty::IntTy::I128),
389                 },
390                 chalk_ir::Scalar::Uint(int_ty) => match int_ty {
391                     chalk_ir::UintTy::Usize => ty::Uint(ty::UintTy::Usize),
392                     chalk_ir::UintTy::U8 => ty::Uint(ty::UintTy::U8),
393                     chalk_ir::UintTy::U16 => ty::Uint(ty::UintTy::U16),
394                     chalk_ir::UintTy::U32 => ty::Uint(ty::UintTy::U32),
395                     chalk_ir::UintTy::U64 => ty::Uint(ty::UintTy::U64),
396                     chalk_ir::UintTy::U128 => ty::Uint(ty::UintTy::U128),
397                 },
398                 chalk_ir::Scalar::Float(float_ty) => match float_ty {
399                     chalk_ir::FloatTy::F32 => ty::Float(ty::FloatTy::F32),
400                     chalk_ir::FloatTy::F64 => ty::Float(ty::FloatTy::F64),
401                 },
402             },
403             TyKind::Array(ty, c) => {
404                 let ty = ty.lower_into(interner);
405                 let c = c.lower_into(interner);
406                 ty::Array(ty, c)
407             }
408             TyKind::FnDef(id, substitution) => ty::FnDef(id.0, substitution.lower_into(interner)),
409             TyKind::Closure(closure, substitution) => {
410                 ty::Closure(closure.0, substitution.lower_into(interner))
411             }
412             TyKind::Generator(..) => unimplemented!(),
413             TyKind::GeneratorWitness(..) => unimplemented!(),
414             TyKind::Never => ty::Never,
415             TyKind::Tuple(_len, substitution) => {
416                 ty::Tuple(substitution.lower_into(interner).try_as_type_list().unwrap())
417             }
418             TyKind::Slice(ty) => ty::Slice(ty.lower_into(interner)),
419             TyKind::Raw(mutbl, ty) => ty::RawPtr(ty::TypeAndMut {
420                 ty: ty.lower_into(interner),
421                 mutbl: mutbl.lower_into(interner),
422             }),
423             TyKind::Ref(mutbl, lifetime, ty) => ty::Ref(
424                 lifetime.lower_into(interner),
425                 ty.lower_into(interner),
426                 mutbl.lower_into(interner),
427             ),
428             TyKind::Str => ty::Str,
429             TyKind::OpaqueType(opaque_ty, substitution) => {
430                 ty::Opaque(opaque_ty.0, substitution.lower_into(interner))
431             }
432             TyKind::AssociatedType(assoc_ty, substitution) => ty::Projection(ty::ProjectionTy {
433                 substs: substitution.lower_into(interner),
434                 item_def_id: assoc_ty.0,
435             }),
436             TyKind::Foreign(def_id) => ty::Foreign(def_id.0),
437             TyKind::Error => return interner.tcx.ty_error(),
438             TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
439                 universe: ty::UniverseIndex::from_usize(placeholder.ui.counter),
440                 name: ty::BoundVar::from_usize(placeholder.idx),
441             }),
442             TyKind::Alias(alias_ty) => match alias_ty {
443                 chalk_ir::AliasTy::Projection(projection) => ty::Projection(ty::ProjectionTy {
444                     item_def_id: projection.associated_ty_id.0,
445                     substs: projection.substitution.lower_into(interner),
446                 }),
447                 chalk_ir::AliasTy::Opaque(opaque) => {
448                     ty::Opaque(opaque.opaque_ty_id.0, opaque.substitution.lower_into(interner))
449                 }
450             },
451             TyKind::Function(_quantified_ty) => unimplemented!(),
452             TyKind::BoundVar(_bound) => ty::Bound(
453                 ty::DebruijnIndex::from_usize(_bound.debruijn.depth() as usize),
454                 ty::BoundTy {
455                     var: ty::BoundVar::from_usize(_bound.index),
456                     kind: ty::BoundTyKind::Anon,
457                 },
458             ),
459             TyKind::InferenceVar(_, _) => unimplemented!(),
460             TyKind::Dyn(_) => unimplemented!(),
461         };
462         interner.tcx.mk_ty(kind)
463     }
464 }
465
466 impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'tcx> {
467     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Lifetime<RustInterner<'tcx>> {
468         match *self {
469             ty::ReEarlyBound(_) => {
470                 panic!("Should have already been substituted.");
471             }
472             ty::ReLateBound(db, br) => chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new(
473                 chalk_ir::DebruijnIndex::new(db.as_u32()),
474                 br.var.as_usize(),
475             ))
476             .intern(interner),
477             ty::ReFree(_) => unimplemented!(),
478             ty::ReStatic => chalk_ir::LifetimeData::Static.intern(interner),
479             ty::ReVar(_) => unimplemented!(),
480             ty::RePlaceholder(placeholder_region) => {
481                 chalk_ir::LifetimeData::Placeholder(chalk_ir::PlaceholderIndex {
482                     ui: chalk_ir::UniverseIndex { counter: placeholder_region.universe.index() },
483                     idx: 0,
484                 })
485                 .intern(interner)
486             }
487             ty::ReEmpty(ui) => {
488                 chalk_ir::LifetimeData::Empty(chalk_ir::UniverseIndex { counter: ui.index() })
489                     .intern(interner)
490             }
491             ty::ReErased => chalk_ir::LifetimeData::Erased.intern(interner),
492         }
493     }
494 }
495
496 impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'tcx>> {
497     fn lower_into(self, interner: RustInterner<'tcx>) -> Region<'tcx> {
498         let kind = match self.data(interner) {
499             chalk_ir::LifetimeData::BoundVar(var) => ty::ReLateBound(
500                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
501                 ty::BoundRegion {
502                     var: ty::BoundVar::from_usize(var.index),
503                     kind: ty::BrAnon(var.index as u32),
504                 },
505             ),
506             chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
507             chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
508                 universe: ty::UniverseIndex::from_usize(p.ui.counter),
509                 name: ty::BoundRegionKind::BrAnon(p.idx as u32),
510             }),
511             chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
512             chalk_ir::LifetimeData::Empty(ui) => {
513                 ty::ReEmpty(ty::UniverseIndex::from_usize(ui.counter))
514             }
515             chalk_ir::LifetimeData::Erased => return interner.tcx.lifetimes.re_erased,
516             chalk_ir::LifetimeData::Phantom(void, _) => match *void {},
517         };
518         interner.tcx.mk_region(kind)
519     }
520 }
521
522 impl<'tcx> LowerInto<'tcx, chalk_ir::Const<RustInterner<'tcx>>> for ty::Const<'tcx> {
523     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Const<RustInterner<'tcx>> {
524         let ty = self.ty().lower_into(interner);
525         let value = match self.kind() {
526             ty::ConstKind::Value(val) => {
527                 chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: val })
528             }
529             ty::ConstKind::Bound(db, bound) => chalk_ir::ConstValue::BoundVar(
530                 chalk_ir::BoundVar::new(chalk_ir::DebruijnIndex::new(db.as_u32()), bound.index()),
531             ),
532             _ => unimplemented!("Const not implemented. {:?}", self),
533         };
534         chalk_ir::ConstData { ty, value }.intern(interner)
535     }
536 }
537
538 impl<'tcx> LowerInto<'tcx, ty::Const<'tcx>> for &chalk_ir::Const<RustInterner<'tcx>> {
539     fn lower_into(self, interner: RustInterner<'tcx>) -> ty::Const<'tcx> {
540         let data = self.data(interner);
541         let ty = data.ty.lower_into(interner);
542         let kind = match data.value {
543             chalk_ir::ConstValue::BoundVar(var) => ty::ConstKind::Bound(
544                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
545                 ty::BoundVar::from_u32(var.index as u32),
546             ),
547             chalk_ir::ConstValue::InferenceVar(_var) => unimplemented!(),
548             chalk_ir::ConstValue::Placeholder(_p) => unimplemented!(),
549             chalk_ir::ConstValue::Concrete(c) => ty::ConstKind::Value(c.interned),
550         };
551         interner.tcx.mk_const(ty::ConstS { ty, kind })
552     }
553 }
554
555 impl<'tcx> LowerInto<'tcx, chalk_ir::GenericArg<RustInterner<'tcx>>> for GenericArg<'tcx> {
556     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GenericArg<RustInterner<'tcx>> {
557         match self.unpack() {
558             ty::subst::GenericArgKind::Type(ty) => {
559                 chalk_ir::GenericArgData::Ty(ty.lower_into(interner))
560             }
561             ty::subst::GenericArgKind::Lifetime(lifetime) => {
562                 chalk_ir::GenericArgData::Lifetime(lifetime.lower_into(interner))
563             }
564             ty::subst::GenericArgKind::Const(c) => {
565                 chalk_ir::GenericArgData::Const(c.lower_into(interner))
566             }
567         }
568         .intern(interner)
569     }
570 }
571
572 impl<'tcx> LowerInto<'tcx, ty::subst::GenericArg<'tcx>>
573     for &chalk_ir::GenericArg<RustInterner<'tcx>>
574 {
575     fn lower_into(self, interner: RustInterner<'tcx>) -> ty::subst::GenericArg<'tcx> {
576         match self.data(interner) {
577             chalk_ir::GenericArgData::Ty(ty) => {
578                 let t: Ty<'tcx> = ty.lower_into(interner);
579                 t.into()
580             }
581             chalk_ir::GenericArgData::Lifetime(lifetime) => {
582                 let r: Region<'tcx> = lifetime.lower_into(interner);
583                 r.into()
584             }
585             chalk_ir::GenericArgData::Const(c) => {
586                 let c: ty::Const<'tcx> = c.lower_into(interner);
587                 c.into()
588             }
589         }
590     }
591 }
592
593 // We lower into an Option here since there are some predicates which Chalk
594 // doesn't have a representation for yet (as a `WhereClause`), but are so common
595 // that we just are accepting the unsoundness for now. The `Option` will
596 // eventually be removed.
597 impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>>
598     for ty::Predicate<'tcx>
599 {
600     fn lower_into(
601         self,
602         interner: RustInterner<'tcx>,
603     ) -> Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> {
604         let (predicate, binders, _named_regions) =
605             collect_bound_vars(interner, interner.tcx, self.kind());
606         let value = match predicate {
607             ty::PredicateKind::Trait(predicate) => {
608                 Some(chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)))
609             }
610             ty::PredicateKind::RegionOutlives(predicate) => {
611                 Some(chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
612                     a: predicate.0.lower_into(interner),
613                     b: predicate.1.lower_into(interner),
614                 }))
615             }
616             ty::PredicateKind::TypeOutlives(predicate) => {
617                 Some(chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
618                     ty: predicate.0.lower_into(interner),
619                     lifetime: predicate.1.lower_into(interner),
620                 }))
621             }
622             ty::PredicateKind::Projection(predicate) => {
623                 Some(chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)))
624             }
625             ty::PredicateKind::WellFormed(_ty) => None,
626
627             ty::PredicateKind::ObjectSafe(..)
628             | ty::PredicateKind::ClosureKind(..)
629             | ty::PredicateKind::Subtype(..)
630             | ty::PredicateKind::Coerce(..)
631             | ty::PredicateKind::ConstEvaluatable(..)
632             | ty::PredicateKind::ConstEquate(..)
633             | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
634                 bug!("unexpected predicate {}", &self)
635             }
636         };
637         value.map(|value| chalk_ir::Binders::new(binders, value))
638     }
639 }
640
641 impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<RustInterner<'tcx>>>>
642     for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>
643 {
644     fn lower_into(
645         self,
646         interner: RustInterner<'tcx>,
647     ) -> chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<RustInterner<'tcx>>> {
648         // `Self` has one binder:
649         // Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
650         // The return type has two:
651         // Binders<&[Binders<WhereClause<I>>]>
652         // This means that any variables that are escaping `self` need to be
653         // shifted in by one so that they are still escaping.
654         let predicates = ty::fold::shift_vars(interner.tcx, self, 1);
655
656         let self_ty = interner.tcx.mk_ty(ty::Bound(
657             // This is going to be wrapped in a binder
658             ty::DebruijnIndex::from_usize(1),
659             ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon },
660         ));
661         let where_clauses = predicates.into_iter().map(|predicate| {
662             let (predicate, binders, _named_regions) =
663                 collect_bound_vars(interner, interner.tcx, predicate);
664             match predicate {
665                 ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id, substs }) => {
666                     chalk_ir::Binders::new(
667                         binders.clone(),
668                         chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef {
669                             trait_id: chalk_ir::TraitId(def_id),
670                             substitution: interner
671                                 .tcx
672                                 .mk_substs_trait(self_ty, substs)
673                                 .lower_into(interner),
674                         }),
675                     )
676                 }
677                 ty::ExistentialPredicate::Projection(predicate) => chalk_ir::Binders::new(
678                     binders.clone(),
679                     chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
680                         alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
681                             associated_ty_id: chalk_ir::AssocTypeId(predicate.item_def_id),
682                             substitution: interner
683                                 .tcx
684                                 .mk_substs_trait(self_ty, predicate.substs)
685                                 .lower_into(interner),
686                         }),
687                         // FIXME(associated_const_equality): teach chalk about terms for alias eq.
688                         ty: predicate.term.ty().unwrap().lower_into(interner),
689                     }),
690                 ),
691                 ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new(
692                     binders.clone(),
693                     chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef {
694                         trait_id: chalk_ir::TraitId(def_id),
695                         substitution: interner
696                             .tcx
697                             .mk_substs_trait(self_ty, &[])
698                             .lower_into(interner),
699                     }),
700                 ),
701             }
702         });
703
704         // Binder for the bound variable representing the concrete underlying type.
705         let existential_binder = chalk_ir::VariableKinds::from1(
706             interner,
707             chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
708         );
709         let value = chalk_ir::QuantifiedWhereClauses::from_iter(interner, where_clauses);
710         chalk_ir::Binders::new(existential_binder, value)
711     }
712 }
713
714 impl<'tcx> LowerInto<'tcx, chalk_ir::FnSig<RustInterner<'tcx>>>
715     for ty::Binder<'tcx, ty::FnSig<'tcx>>
716 {
717     fn lower_into(self, _interner: RustInterner<'_>) -> FnSig<RustInterner<'tcx>> {
718         chalk_ir::FnSig {
719             abi: self.abi(),
720             safety: match self.unsafety() {
721                 Unsafety::Normal => chalk_ir::Safety::Safe,
722                 Unsafety::Unsafe => chalk_ir::Safety::Unsafe,
723             },
724             variadic: self.c_variadic(),
725         }
726     }
727 }
728
729 // We lower into an Option here since there are some predicates which Chalk
730 // doesn't have a representation for yet (as an `InlineBound`). The `Option` will
731 // eventually be removed.
732 impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>>>
733     for ty::Predicate<'tcx>
734 {
735     fn lower_into(
736         self,
737         interner: RustInterner<'tcx>,
738     ) -> Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>> {
739         let (predicate, binders, _named_regions) =
740             collect_bound_vars(interner, interner.tcx, self.kind());
741         match predicate {
742             ty::PredicateKind::Trait(predicate) => Some(chalk_ir::Binders::new(
743                 binders,
744                 chalk_solve::rust_ir::InlineBound::TraitBound(
745                     predicate.trait_ref.lower_into(interner),
746                 ),
747             )),
748             ty::PredicateKind::Projection(predicate) => Some(chalk_ir::Binders::new(
749                 binders,
750                 chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
751             )),
752             ty::PredicateKind::TypeOutlives(_predicate) => None,
753             ty::PredicateKind::WellFormed(_ty) => None,
754
755             ty::PredicateKind::RegionOutlives(..)
756             | ty::PredicateKind::ObjectSafe(..)
757             | ty::PredicateKind::ClosureKind(..)
758             | ty::PredicateKind::Subtype(..)
759             | ty::PredicateKind::Coerce(..)
760             | ty::PredicateKind::ConstEvaluatable(..)
761             | ty::PredicateKind::ConstEquate(..)
762             | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
763                 bug!("unexpected predicate {}", &self)
764             }
765         }
766     }
767 }
768
769 impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>>>
770     for ty::TraitRef<'tcx>
771 {
772     fn lower_into(
773         self,
774         interner: RustInterner<'tcx>,
775     ) -> chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>> {
776         chalk_solve::rust_ir::TraitBound {
777             trait_id: chalk_ir::TraitId(self.def_id),
778             args_no_self: self.substs[1..].iter().map(|arg| arg.lower_into(interner)).collect(),
779         }
780     }
781 }
782
783 impl<'tcx> LowerInto<'tcx, chalk_ir::Mutability> for ast::Mutability {
784     fn lower_into(self, _interner: RustInterner<'tcx>) -> chalk_ir::Mutability {
785         match self {
786             rustc_ast::Mutability::Mut => chalk_ir::Mutability::Mut,
787             rustc_ast::Mutability::Not => chalk_ir::Mutability::Not,
788         }
789     }
790 }
791
792 impl<'tcx> LowerInto<'tcx, ast::Mutability> for chalk_ir::Mutability {
793     fn lower_into(self, _interner: RustInterner<'tcx>) -> ast::Mutability {
794         match self {
795             chalk_ir::Mutability::Mut => ast::Mutability::Mut,
796             chalk_ir::Mutability::Not => ast::Mutability::Not,
797         }
798     }
799 }
800
801 impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::Polarity> for ty::ImplPolarity {
802     fn lower_into(self, _interner: RustInterner<'tcx>) -> chalk_solve::rust_ir::Polarity {
803         match self {
804             ty::ImplPolarity::Positive => chalk_solve::rust_ir::Polarity::Positive,
805             ty::ImplPolarity::Negative => chalk_solve::rust_ir::Polarity::Negative,
806             // FIXME(chalk) reservation impls
807             ty::ImplPolarity::Reservation => chalk_solve::rust_ir::Polarity::Negative,
808         }
809     }
810 }
811 impl<'tcx> LowerInto<'tcx, chalk_ir::Variance> for ty::Variance {
812     fn lower_into(self, _interner: RustInterner<'tcx>) -> chalk_ir::Variance {
813         match self {
814             ty::Variance::Covariant => chalk_ir::Variance::Covariant,
815             ty::Variance::Invariant => chalk_ir::Variance::Invariant,
816             ty::Variance::Contravariant => chalk_ir::Variance::Contravariant,
817             ty::Variance::Bivariant => unimplemented!(),
818         }
819     }
820 }
821
822 impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>>>
823     for ty::ProjectionPredicate<'tcx>
824 {
825     fn lower_into(
826         self,
827         interner: RustInterner<'tcx>,
828     ) -> chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>> {
829         let (trait_ref, own_substs) = self.projection_ty.trait_ref_and_own_substs(interner.tcx);
830         chalk_solve::rust_ir::AliasEqBound {
831             trait_bound: trait_ref.lower_into(interner),
832             associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
833             parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(),
834             value: self.term.ty().unwrap().lower_into(interner),
835         }
836     }
837 }
838
839 /// To collect bound vars, we have to do two passes. In the first pass, we
840 /// collect all `BoundRegionKind`s and `ty::Bound`s. In the second pass, we then
841 /// replace `BrNamed` into `BrAnon`. The two separate passes are important,
842 /// since we can only replace `BrNamed` with `BrAnon`s with indices *after* all
843 /// "real" `BrAnon`s.
844 ///
845 /// It's important to note that because of prior substitution, we may have
846 /// late-bound regions, even outside of fn contexts, since this is the best way
847 /// to prep types for chalk lowering.
848 pub(crate) fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>(
849     interner: RustInterner<'tcx>,
850     tcx: TyCtxt<'tcx>,
851     ty: Binder<'tcx, T>,
852 ) -> (T, chalk_ir::VariableKinds<RustInterner<'tcx>>, BTreeMap<DefId, u32>) {
853     let mut bound_vars_collector = BoundVarsCollector::new();
854     ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector);
855     let mut parameters = bound_vars_collector.parameters;
856     let named_parameters: BTreeMap<DefId, u32> = bound_vars_collector
857         .named_parameters
858         .into_iter()
859         .enumerate()
860         .map(|(i, def_id)| (def_id, (i + parameters.len()) as u32))
861         .collect();
862
863     let mut bound_var_substitutor = NamedBoundVarSubstitutor::new(tcx, &named_parameters);
864     let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor);
865
866     for var in named_parameters.values() {
867         parameters.insert(*var, chalk_ir::VariableKind::Lifetime);
868     }
869
870     (0..parameters.len()).for_each(|i| {
871         parameters
872             .get(&(i as u32))
873             .or_else(|| bug!("Skipped bound var index: parameters={:?}", parameters));
874     });
875
876     let binders =
877         chalk_ir::VariableKinds::from_iter(interner, parameters.into_iter().map(|(_, v)| v));
878
879     (new_ty, binders, named_parameters)
880 }
881
882 pub(crate) struct BoundVarsCollector<'tcx> {
883     binder_index: ty::DebruijnIndex,
884     pub(crate) parameters: BTreeMap<u32, chalk_ir::VariableKind<RustInterner<'tcx>>>,
885     pub(crate) named_parameters: Vec<DefId>,
886 }
887
888 impl<'tcx> BoundVarsCollector<'tcx> {
889     pub(crate) fn new() -> Self {
890         BoundVarsCollector {
891             binder_index: ty::INNERMOST,
892             parameters: BTreeMap::new(),
893             named_parameters: vec![],
894         }
895     }
896 }
897
898 impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
899     fn visit_binder<T: TypeFoldable<'tcx>>(
900         &mut self,
901         t: &Binder<'tcx, T>,
902     ) -> ControlFlow<Self::BreakTy> {
903         self.binder_index.shift_in(1);
904         let result = t.super_visit_with(self);
905         self.binder_index.shift_out(1);
906         result
907     }
908
909     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
910         match *t.kind() {
911             ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
912                 match self.parameters.entry(bound_ty.var.as_u32()) {
913                     Entry::Vacant(entry) => {
914                         entry.insert(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General));
915                     }
916                     Entry::Occupied(entry) => match entry.get() {
917                         chalk_ir::VariableKind::Ty(_) => {}
918                         _ => panic!(),
919                     },
920                 }
921             }
922
923             _ => (),
924         };
925
926         t.super_visit_with(self)
927     }
928
929     fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
930         match *r {
931             ty::ReLateBound(index, br) if index == self.binder_index => match br.kind {
932                 ty::BoundRegionKind::BrNamed(def_id, _name) => {
933                     if !self.named_parameters.iter().any(|d| *d == def_id) {
934                         self.named_parameters.push(def_id);
935                     }
936                 }
937
938                 ty::BoundRegionKind::BrAnon(var) => match self.parameters.entry(var) {
939                     Entry::Vacant(entry) => {
940                         entry.insert(chalk_ir::VariableKind::Lifetime);
941                     }
942                     Entry::Occupied(entry) => match entry.get() {
943                         chalk_ir::VariableKind::Lifetime => {}
944                         _ => panic!(),
945                     },
946                 },
947
948                 ty::BoundRegionKind::BrEnv => unimplemented!(),
949             },
950
951             ty::ReEarlyBound(_re) => {
952                 // FIXME(chalk): jackh726 - I think we should always have already
953                 // substituted away `ReEarlyBound`s for `ReLateBound`s, but need to confirm.
954                 unimplemented!();
955             }
956
957             _ => (),
958         };
959
960         r.super_visit_with(self)
961     }
962 }
963
964 /// This is used to replace `BoundRegionKind::BrNamed` with `BoundRegionKind::BrAnon`.
965 /// Note: we assume that we will always have room for more bound vars. (i.e. we
966 /// won't ever hit the `u32` limit in `BrAnon`s).
967 struct NamedBoundVarSubstitutor<'a, 'tcx> {
968     tcx: TyCtxt<'tcx>,
969     binder_index: ty::DebruijnIndex,
970     named_parameters: &'a BTreeMap<DefId, u32>,
971 }
972
973 impl<'a, 'tcx> NamedBoundVarSubstitutor<'a, 'tcx> {
974     fn new(tcx: TyCtxt<'tcx>, named_parameters: &'a BTreeMap<DefId, u32>) -> Self {
975         NamedBoundVarSubstitutor { tcx, binder_index: ty::INNERMOST, named_parameters }
976     }
977 }
978
979 impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
980     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
981         self.tcx
982     }
983
984     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> {
985         self.binder_index.shift_in(1);
986         let result = t.super_fold_with(self);
987         self.binder_index.shift_out(1);
988         result
989     }
990
991     fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
992         match *r {
993             ty::ReLateBound(index, br) if index == self.binder_index => match br.kind {
994                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
995                     Some(idx) => {
996                         let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) };
997                         return self.tcx.mk_region(ty::ReLateBound(index, new_br));
998                     }
999                     None => panic!("Missing `BrNamed`."),
1000                 },
1001                 ty::BrEnv => unimplemented!(),
1002                 ty::BrAnon(_) => {}
1003             },
1004             _ => (),
1005         };
1006
1007         r.super_fold_with(self)
1008     }
1009 }
1010
1011 /// Used to substitute `Param`s with placeholders. We do this since Chalk
1012 /// have a notion of `Param`s.
1013 pub(crate) struct ParamsSubstitutor<'tcx> {
1014     tcx: TyCtxt<'tcx>,
1015     binder_index: ty::DebruijnIndex,
1016     list: Vec<rustc_middle::ty::ParamTy>,
1017     next_ty_placeholder: usize,
1018     pub(crate) params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
1019     pub(crate) named_regions: BTreeMap<DefId, u32>,
1020 }
1021
1022 impl<'tcx> ParamsSubstitutor<'tcx> {
1023     pub(crate) fn new(tcx: TyCtxt<'tcx>, next_ty_placeholder: usize) -> Self {
1024         ParamsSubstitutor {
1025             tcx,
1026             binder_index: ty::INNERMOST,
1027             list: vec![],
1028             next_ty_placeholder,
1029             params: rustc_data_structures::fx::FxHashMap::default(),
1030             named_regions: BTreeMap::default(),
1031         }
1032     }
1033 }
1034
1035 impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
1036     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
1037         self.tcx
1038     }
1039
1040     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> {
1041         self.binder_index.shift_in(1);
1042         let result = t.super_fold_with(self);
1043         self.binder_index.shift_out(1);
1044         result
1045     }
1046
1047     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
1048         match *t.kind() {
1049             ty::Param(param) => match self.list.iter().position(|r| r == &param) {
1050                 Some(idx) => self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
1051                     universe: ty::UniverseIndex::from_usize(0),
1052                     name: ty::BoundVar::from_usize(idx),
1053                 })),
1054                 None => {
1055                     self.list.push(param);
1056                     let idx = self.list.len() - 1 + self.next_ty_placeholder;
1057                     self.params.insert(idx, param);
1058                     self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
1059                         universe: ty::UniverseIndex::from_usize(0),
1060                         name: ty::BoundVar::from_usize(idx),
1061                     }))
1062                 }
1063             },
1064             _ => t.super_fold_with(self),
1065         }
1066     }
1067
1068     fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
1069         match *r {
1070             // FIXME(chalk) - jackh726 - this currently isn't hit in any tests,
1071             // since canonicalization will already change these to canonical
1072             // variables (ty::ReLateBound).
1073             ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) {
1074                 Some(idx) => {
1075                     let br = ty::BoundRegion {
1076                         var: ty::BoundVar::from_u32(*idx),
1077                         kind: ty::BrAnon(*idx),
1078                     };
1079                     self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
1080                 }
1081                 None => {
1082                     let idx = self.named_regions.len() as u32;
1083                     let br =
1084                         ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
1085                     self.named_regions.insert(_re.def_id, idx);
1086                     self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
1087                 }
1088             },
1089
1090             _ => r.super_fold_with(self),
1091         }
1092     }
1093 }
1094
1095 pub(crate) struct ReverseParamsSubstitutor<'tcx> {
1096     tcx: TyCtxt<'tcx>,
1097     params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
1098 }
1099
1100 impl<'tcx> ReverseParamsSubstitutor<'tcx> {
1101     pub(crate) fn new(
1102         tcx: TyCtxt<'tcx>,
1103         params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
1104     ) -> Self {
1105         Self { tcx, params }
1106     }
1107 }
1108
1109 impl<'tcx> TypeFolder<'tcx> for ReverseParamsSubstitutor<'tcx> {
1110     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
1111         self.tcx
1112     }
1113
1114     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
1115         match *t.kind() {
1116             ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, name }) => {
1117                 match self.params.get(&name.as_usize()) {
1118                     Some(param) => self.tcx.mk_ty(ty::Param(*param)),
1119                     None => t,
1120                 }
1121             }
1122
1123             _ => t.super_fold_with(self),
1124         }
1125     }
1126 }
1127
1128 /// Used to collect `Placeholder`s.
1129 pub(crate) struct PlaceholdersCollector {
1130     universe_index: ty::UniverseIndex,
1131     pub(crate) next_ty_placeholder: usize,
1132     pub(crate) next_anon_region_placeholder: u32,
1133 }
1134
1135 impl PlaceholdersCollector {
1136     pub(crate) fn new() -> Self {
1137         PlaceholdersCollector {
1138             universe_index: ty::UniverseIndex::ROOT,
1139             next_ty_placeholder: 0,
1140             next_anon_region_placeholder: 0,
1141         }
1142     }
1143 }
1144
1145 impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
1146     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1147         match t.kind() {
1148             ty::Placeholder(p) if p.universe == self.universe_index => {
1149                 self.next_ty_placeholder = self.next_ty_placeholder.max(p.name.as_usize() + 1);
1150             }
1151
1152             _ => (),
1153         };
1154
1155         t.super_visit_with(self)
1156     }
1157
1158     fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
1159         match *r {
1160             ty::RePlaceholder(p) if p.universe == self.universe_index => {
1161                 if let ty::BoundRegionKind::BrAnon(anon) = p.name {
1162                     self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
1163                 }
1164             }
1165
1166             _ => (),
1167         };
1168
1169         r.super_visit_with(self)
1170     }
1171 }