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