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