diff options
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 970 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/interner.rs | 298 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/mapping.rs | 672 |
3 files changed, 982 insertions, 958 deletions
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 7d3ad6eb4..6c286ead7 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -1,325 +1,29 @@ | |||
1 | //! Conversion code from/to Chalk. | 1 | //! Conversion code from/to Chalk. |
2 | use std::{fmt, sync::Arc}; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{ | 6 | use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; |
7 | cast::Cast, fold::shift::Shift, interner::HasInterner, GenericArg, Goal, GoalData, | ||
8 | PlaceholderIndex, Scalar, TypeName, UniverseIndex, | ||
9 | }; | ||
10 | 7 | ||
11 | use hir_def::{ | 8 | use hir_def::{ |
12 | lang_item::{lang_attr, LangItemTarget}, | 9 | lang_item::{lang_attr, LangItemTarget}, |
13 | type_ref::Mutability, | 10 | AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, |
14 | AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId, | ||
15 | }; | ||
16 | use ra_db::{ | ||
17 | salsa::{InternId, InternKey}, | ||
18 | CrateId, | ||
19 | }; | 11 | }; |
12 | use ra_db::{salsa::InternKey, CrateId}; | ||
20 | 13 | ||
21 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 14 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; |
22 | use crate::{ | 15 | use crate::{ |
23 | db::HirDatabase, | 16 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, |
24 | display::HirDisplay, | 17 | DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, |
25 | method_resolution::TyFingerprint, | ||
26 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, | ||
27 | utils::generics, | ||
28 | ApplicationTy, DebruijnIndex, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | ||
29 | }; | 18 | }; |
30 | use chalk_rust_ir::WellKnownTrait; | 19 | use chalk_rust_ir::WellKnownTrait; |
20 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; | ||
31 | 21 | ||
32 | pub(super) mod tls; | 22 | pub use self::interner::*; |
33 | |||
34 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] | ||
35 | pub struct Interner; | ||
36 | |||
37 | impl chalk_ir::interner::Interner for Interner { | ||
38 | type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? | ||
39 | type InternedLifetime = chalk_ir::LifetimeData<Self>; | ||
40 | type InternedConst = Arc<chalk_ir::ConstData<Self>>; | ||
41 | type InternedConcreteConst = (); | ||
42 | type InternedGenericArg = chalk_ir::GenericArgData<Self>; | ||
43 | type InternedGoal = Arc<GoalData<Self>>; | ||
44 | type InternedGoals = Vec<Goal<Self>>; | ||
45 | type InternedSubstitution = Vec<GenericArg<Self>>; | ||
46 | type InternedProgramClause = chalk_ir::ProgramClauseData<Self>; | ||
47 | type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; | ||
48 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; | ||
49 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; | ||
50 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; | ||
51 | type DefId = InternId; | ||
52 | type InternedAdtId = InternId; | ||
53 | type Identifier = TypeAliasId; | ||
54 | |||
55 | fn debug_adt_id(type_kind_id: StructId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
56 | tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) | ||
57 | } | ||
58 | |||
59 | fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
60 | tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) | ||
61 | } | ||
62 | |||
63 | fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
64 | tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) | ||
65 | } | ||
66 | |||
67 | fn debug_alias( | ||
68 | alias: &chalk_ir::AliasTy<Interner>, | ||
69 | fmt: &mut fmt::Formatter<'_>, | ||
70 | ) -> Option<fmt::Result> { | ||
71 | tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) | ||
72 | } | ||
73 | |||
74 | fn debug_projection_ty( | ||
75 | proj: &chalk_ir::ProjectionTy<Interner>, | ||
76 | fmt: &mut fmt::Formatter<'_>, | ||
77 | ) -> Option<fmt::Result> { | ||
78 | tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) | ||
79 | } | ||
80 | |||
81 | fn debug_opaque_ty( | ||
82 | opaque_ty: &chalk_ir::OpaqueTy<Interner>, | ||
83 | fmt: &mut fmt::Formatter<'_>, | ||
84 | ) -> Option<fmt::Result> { | ||
85 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt))) | ||
86 | } | ||
87 | |||
88 | fn debug_opaque_ty_id( | ||
89 | opaque_ty_id: chalk_ir::OpaqueTyId<Self>, | ||
90 | fmt: &mut fmt::Formatter<'_>, | ||
91 | ) -> Option<fmt::Result> { | ||
92 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt))) | ||
93 | } | ||
94 | |||
95 | fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
96 | tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) | ||
97 | } | ||
98 | |||
99 | fn debug_lifetime( | ||
100 | lifetime: &chalk_ir::Lifetime<Interner>, | ||
101 | fmt: &mut fmt::Formatter<'_>, | ||
102 | ) -> Option<fmt::Result> { | ||
103 | tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt))) | ||
104 | } | ||
105 | |||
106 | fn debug_generic_arg( | ||
107 | parameter: &GenericArg<Interner>, | ||
108 | fmt: &mut fmt::Formatter<'_>, | ||
109 | ) -> Option<fmt::Result> { | ||
110 | tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) | ||
111 | } | ||
112 | |||
113 | fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
114 | tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt))) | ||
115 | } | ||
116 | |||
117 | fn debug_goals( | ||
118 | goals: &chalk_ir::Goals<Interner>, | ||
119 | fmt: &mut fmt::Formatter<'_>, | ||
120 | ) -> Option<fmt::Result> { | ||
121 | tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt))) | ||
122 | } | ||
123 | |||
124 | fn debug_program_clause_implication( | ||
125 | pci: &chalk_ir::ProgramClauseImplication<Interner>, | ||
126 | fmt: &mut fmt::Formatter<'_>, | ||
127 | ) -> Option<fmt::Result> { | ||
128 | tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt))) | ||
129 | } | ||
130 | |||
131 | fn debug_application_ty( | ||
132 | application_ty: &chalk_ir::ApplicationTy<Interner>, | ||
133 | fmt: &mut fmt::Formatter<'_>, | ||
134 | ) -> Option<fmt::Result> { | ||
135 | tls::with_current_program(|prog| Some(prog?.debug_application_ty(application_ty, fmt))) | ||
136 | } | ||
137 | |||
138 | fn debug_substitution( | ||
139 | substitution: &chalk_ir::Substitution<Interner>, | ||
140 | fmt: &mut fmt::Formatter<'_>, | ||
141 | ) -> Option<fmt::Result> { | ||
142 | tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt))) | ||
143 | } | ||
144 | |||
145 | fn debug_separator_trait_ref( | ||
146 | separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>, | ||
147 | fmt: &mut fmt::Formatter<'_>, | ||
148 | ) -> Option<fmt::Result> { | ||
149 | tls::with_current_program(|prog| { | ||
150 | Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt)) | ||
151 | }) | ||
152 | } | ||
153 | |||
154 | fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { | ||
155 | Box::new(ty) | ||
156 | } | ||
157 | |||
158 | fn ty_data<'a>(&self, ty: &'a Box<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> { | ||
159 | ty | ||
160 | } | ||
161 | |||
162 | fn intern_lifetime( | ||
163 | &self, | ||
164 | lifetime: chalk_ir::LifetimeData<Self>, | ||
165 | ) -> chalk_ir::LifetimeData<Self> { | ||
166 | lifetime | ||
167 | } | ||
168 | |||
169 | fn lifetime_data<'a>( | ||
170 | &self, | ||
171 | lifetime: &'a chalk_ir::LifetimeData<Self>, | ||
172 | ) -> &'a chalk_ir::LifetimeData<Self> { | ||
173 | lifetime | ||
174 | } | ||
175 | |||
176 | fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Arc<chalk_ir::ConstData<Self>> { | ||
177 | Arc::new(constant) | ||
178 | } | ||
179 | |||
180 | fn const_data<'a>( | ||
181 | &self, | ||
182 | constant: &'a Arc<chalk_ir::ConstData<Self>>, | ||
183 | ) -> &'a chalk_ir::ConstData<Self> { | ||
184 | constant | ||
185 | } | ||
186 | |||
187 | fn const_eq(&self, _ty: &Box<chalk_ir::TyData<Self>>, _c1: &(), _c2: &()) -> bool { | ||
188 | true | ||
189 | } | ||
190 | |||
191 | fn intern_generic_arg( | ||
192 | &self, | ||
193 | parameter: chalk_ir::GenericArgData<Self>, | ||
194 | ) -> chalk_ir::GenericArgData<Self> { | ||
195 | parameter | ||
196 | } | ||
197 | |||
198 | fn generic_arg_data<'a>( | ||
199 | &self, | ||
200 | parameter: &'a chalk_ir::GenericArgData<Self>, | ||
201 | ) -> &'a chalk_ir::GenericArgData<Self> { | ||
202 | parameter | ||
203 | } | ||
204 | |||
205 | fn intern_goal(&self, goal: GoalData<Self>) -> Arc<GoalData<Self>> { | ||
206 | Arc::new(goal) | ||
207 | } | ||
208 | |||
209 | fn intern_goals<E>( | ||
210 | &self, | ||
211 | data: impl IntoIterator<Item = Result<Goal<Self>, E>>, | ||
212 | ) -> Result<Self::InternedGoals, E> { | ||
213 | data.into_iter().collect() | ||
214 | } | ||
215 | |||
216 | fn goal_data<'a>(&self, goal: &'a Arc<GoalData<Self>>) -> &'a GoalData<Self> { | ||
217 | goal | ||
218 | } | ||
219 | |||
220 | fn goals_data<'a>(&self, goals: &'a Vec<Goal<Interner>>) -> &'a [Goal<Interner>] { | ||
221 | goals | ||
222 | } | ||
223 | |||
224 | fn intern_substitution<E>( | ||
225 | &self, | ||
226 | data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>, | ||
227 | ) -> Result<Vec<GenericArg<Self>>, E> { | ||
228 | data.into_iter().collect() | ||
229 | } | ||
230 | |||
231 | fn substitution_data<'a>( | ||
232 | &self, | ||
233 | substitution: &'a Vec<GenericArg<Self>>, | ||
234 | ) -> &'a [GenericArg<Self>] { | ||
235 | substitution | ||
236 | } | ||
237 | |||
238 | fn intern_program_clause( | ||
239 | &self, | ||
240 | data: chalk_ir::ProgramClauseData<Self>, | ||
241 | ) -> chalk_ir::ProgramClauseData<Self> { | ||
242 | data | ||
243 | } | ||
244 | |||
245 | fn program_clause_data<'a>( | ||
246 | &self, | ||
247 | clause: &'a chalk_ir::ProgramClauseData<Self>, | ||
248 | ) -> &'a chalk_ir::ProgramClauseData<Self> { | ||
249 | clause | ||
250 | } | ||
251 | |||
252 | fn intern_program_clauses<E>( | ||
253 | &self, | ||
254 | data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>, | ||
255 | ) -> Result<Arc<[chalk_ir::ProgramClause<Self>]>, E> { | ||
256 | data.into_iter().collect() | ||
257 | } | ||
258 | |||
259 | fn program_clauses_data<'a>( | ||
260 | &self, | ||
261 | clauses: &'a Arc<[chalk_ir::ProgramClause<Self>]>, | ||
262 | ) -> &'a [chalk_ir::ProgramClause<Self>] { | ||
263 | &clauses | ||
264 | } | ||
265 | |||
266 | fn intern_quantified_where_clauses<E>( | ||
267 | &self, | ||
268 | data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>, | ||
269 | ) -> Result<Self::InternedQuantifiedWhereClauses, E> { | ||
270 | data.into_iter().collect() | ||
271 | } | ||
272 | |||
273 | fn quantified_where_clauses_data<'a>( | ||
274 | &self, | ||
275 | clauses: &'a Self::InternedQuantifiedWhereClauses, | ||
276 | ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] { | ||
277 | clauses | ||
278 | } | ||
279 | |||
280 | fn intern_generic_arg_kinds<E>( | ||
281 | &self, | ||
282 | data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>, | ||
283 | ) -> Result<Self::InternedVariableKinds, E> { | ||
284 | data.into_iter().collect() | ||
285 | } | ||
286 | |||
287 | fn variable_kinds_data<'a>( | ||
288 | &self, | ||
289 | parameter_kinds: &'a Self::InternedVariableKinds, | ||
290 | ) -> &'a [chalk_ir::VariableKind<Self>] { | ||
291 | ¶meter_kinds | ||
292 | } | ||
293 | |||
294 | fn intern_canonical_var_kinds<E>( | ||
295 | &self, | ||
296 | data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>, | ||
297 | ) -> Result<Self::InternedCanonicalVarKinds, E> { | ||
298 | data.into_iter().collect() | ||
299 | } | ||
300 | |||
301 | fn canonical_var_kinds_data<'a>( | ||
302 | &self, | ||
303 | canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, | ||
304 | ) -> &'a [chalk_ir::CanonicalVarKind<Self>] { | ||
305 | &canonical_var_kinds | ||
306 | } | ||
307 | } | ||
308 | 23 | ||
309 | impl chalk_ir::interner::HasInterner for Interner { | 24 | pub(super) mod tls; |
310 | type Interner = Self; | 25 | mod interner; |
311 | } | 26 | mod mapping; |
312 | |||
313 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | ||
314 | pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<Interner>; | ||
315 | pub type TraitId = chalk_ir::TraitId<Interner>; | ||
316 | pub type TraitDatum = chalk_rust_ir::TraitDatum<Interner>; | ||
317 | pub type StructId = chalk_ir::AdtId<Interner>; | ||
318 | pub type StructDatum = chalk_rust_ir::AdtDatum<Interner>; | ||
319 | pub type ImplId = chalk_ir::ImplId<Interner>; | ||
320 | pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>; | ||
321 | pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>; | ||
322 | pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>; | ||
323 | 27 | ||
324 | pub(super) trait ToChalk { | 28 | pub(super) trait ToChalk { |
325 | type Chalk; | 29 | type Chalk; |
@@ -334,656 +38,6 @@ where | |||
334 | T::from_chalk(db, chalk) | 38 | T::from_chalk(db, chalk) |
335 | } | 39 | } |
336 | 40 | ||
337 | impl ToChalk for Ty { | ||
338 | type Chalk = chalk_ir::Ty<Interner>; | ||
339 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { | ||
340 | match self { | ||
341 | Ty::Apply(apply_ty) => { | ||
342 | if let TypeCtor::Ref(m) = apply_ty.ctor { | ||
343 | return ref_to_chalk(db, m, apply_ty.parameters); | ||
344 | } | ||
345 | let name = apply_ty.ctor.to_chalk(db); | ||
346 | let substitution = apply_ty.parameters.to_chalk(db); | ||
347 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | ||
348 | } | ||
349 | Ty::Projection(proj_ty) => { | ||
350 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | ||
351 | let substitution = proj_ty.parameters.to_chalk(db); | ||
352 | chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { | ||
353 | associated_ty_id, | ||
354 | substitution, | ||
355 | }) | ||
356 | .cast(&Interner) | ||
357 | .intern(&Interner) | ||
358 | } | ||
359 | Ty::Placeholder(id) => { | ||
360 | let interned_id = db.intern_type_param_id(id); | ||
361 | PlaceholderIndex { | ||
362 | ui: UniverseIndex::ROOT, | ||
363 | idx: interned_id.as_intern_id().as_usize(), | ||
364 | } | ||
365 | .to_ty::<Interner>(&Interner) | ||
366 | } | ||
367 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), | ||
368 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | ||
369 | Ty::Dyn(predicates) => { | ||
370 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from( | ||
371 | &Interner, | ||
372 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), | ||
373 | ); | ||
374 | let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; | ||
375 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) | ||
376 | } | ||
377 | Ty::Opaque(_) | Ty::Unknown => { | ||
378 | let substitution = chalk_ir::Substitution::empty(&Interner); | ||
379 | let name = TypeName::Error; | ||
380 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { | ||
385 | match chalk.data(&Interner).clone() { | ||
386 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { | ||
387 | TypeName::Error => Ty::Unknown, | ||
388 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), | ||
389 | _ => { | ||
390 | let ctor = from_chalk(db, apply_ty.name); | ||
391 | let parameters = from_chalk(db, apply_ty.substitution); | ||
392 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
393 | } | ||
394 | }, | ||
395 | chalk_ir::TyData::Placeholder(idx) => { | ||
396 | assert_eq!(idx.ui, UniverseIndex::ROOT); | ||
397 | let interned_id = crate::db::GlobalTypeParamId::from_intern_id( | ||
398 | crate::salsa::InternId::from(idx.idx), | ||
399 | ); | ||
400 | Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) | ||
401 | } | ||
402 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => { | ||
403 | let associated_ty = from_chalk(db, proj.associated_ty_id); | ||
404 | let parameters = from_chalk(db, proj.substitution); | ||
405 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | ||
406 | } | ||
407 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), | ||
408 | chalk_ir::TyData::Function(_) => unimplemented!(), | ||
409 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx), | ||
410 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, | ||
411 | chalk_ir::TyData::Dyn(where_clauses) => { | ||
412 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); | ||
413 | let predicates = where_clauses | ||
414 | .bounds | ||
415 | .skip_binders() | ||
416 | .iter(&Interner) | ||
417 | .map(|c| from_chalk(db, c.clone())) | ||
418 | .collect(); | ||
419 | Ty::Dyn(predicates) | ||
420 | } | ||
421 | } | ||
422 | } | ||
423 | } | ||
424 | |||
425 | const LIFETIME_PLACEHOLDER: PlaceholderIndex = | ||
426 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; | ||
427 | |||
428 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a | ||
429 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. | ||
430 | fn ref_to_chalk( | ||
431 | db: &dyn HirDatabase, | ||
432 | mutability: Mutability, | ||
433 | subst: Substs, | ||
434 | ) -> chalk_ir::Ty<Interner> { | ||
435 | let arg = subst[0].clone().to_chalk(db); | ||
436 | let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); | ||
437 | chalk_ir::ApplicationTy { | ||
438 | name: TypeName::Ref(mutability.to_chalk(db)), | ||
439 | substitution: chalk_ir::Substitution::from( | ||
440 | &Interner, | ||
441 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], | ||
442 | ), | ||
443 | } | ||
444 | .intern(&Interner) | ||
445 | } | ||
446 | |||
447 | /// Here we remove the lifetime from the type we got from Chalk. | ||
448 | fn ref_from_chalk( | ||
449 | db: &dyn HirDatabase, | ||
450 | mutability: chalk_ir::Mutability, | ||
451 | subst: chalk_ir::Substitution<Interner>, | ||
452 | ) -> Ty { | ||
453 | let tys = subst | ||
454 | .iter(&Interner) | ||
455 | .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone()))) | ||
456 | .collect(); | ||
457 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) | ||
458 | } | ||
459 | |||
460 | impl ToChalk for Substs { | ||
461 | type Chalk = chalk_ir::Substitution<Interner>; | ||
462 | |||
463 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { | ||
464 | chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) | ||
465 | } | ||
466 | |||
467 | fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { | ||
468 | let tys = parameters | ||
469 | .iter(&Interner) | ||
470 | .map(|p| match p.ty(&Interner) { | ||
471 | Some(ty) => from_chalk(db, ty.clone()), | ||
472 | None => unimplemented!(), | ||
473 | }) | ||
474 | .collect(); | ||
475 | Substs(tys) | ||
476 | } | ||
477 | } | ||
478 | |||
479 | impl ToChalk for TraitRef { | ||
480 | type Chalk = chalk_ir::TraitRef<Interner>; | ||
481 | |||
482 | fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> { | ||
483 | let trait_id = self.trait_.to_chalk(db); | ||
484 | let substitution = self.substs.to_chalk(db); | ||
485 | chalk_ir::TraitRef { trait_id, substitution } | ||
486 | } | ||
487 | |||
488 | fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self { | ||
489 | let trait_ = from_chalk(db, trait_ref.trait_id); | ||
490 | let substs = from_chalk(db, trait_ref.substitution); | ||
491 | TraitRef { trait_, substs } | ||
492 | } | ||
493 | } | ||
494 | |||
495 | impl ToChalk for hir_def::TraitId { | ||
496 | type Chalk = TraitId; | ||
497 | |||
498 | fn to_chalk(self, _db: &dyn HirDatabase) -> TraitId { | ||
499 | chalk_ir::TraitId(self.as_intern_id()) | ||
500 | } | ||
501 | |||
502 | fn from_chalk(_db: &dyn HirDatabase, trait_id: TraitId) -> hir_def::TraitId { | ||
503 | InternKey::from_intern_id(trait_id.0) | ||
504 | } | ||
505 | } | ||
506 | |||
507 | impl ToChalk for TypeCtor { | ||
508 | type Chalk = TypeName<Interner>; | ||
509 | |||
510 | fn to_chalk(self, db: &dyn HirDatabase) -> TypeName<Interner> { | ||
511 | match self { | ||
512 | TypeCtor::AssociatedType(type_alias) => { | ||
513 | let type_id = type_alias.to_chalk(db); | ||
514 | TypeName::AssociatedType(type_id) | ||
515 | } | ||
516 | |||
517 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), | ||
518 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), | ||
519 | TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), | ||
520 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) => { | ||
521 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) | ||
522 | } | ||
523 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) => { | ||
524 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) | ||
525 | } | ||
526 | |||
527 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), | ||
528 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), | ||
529 | TypeCtor::Slice => TypeName::Slice, | ||
530 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), | ||
531 | TypeCtor::Str => TypeName::Str, | ||
532 | |||
533 | TypeCtor::Int(Uncertain::Unknown) | ||
534 | | TypeCtor::Float(Uncertain::Unknown) | ||
535 | | TypeCtor::Adt(_) | ||
536 | | TypeCtor::Array | ||
537 | | TypeCtor::FnDef(_) | ||
538 | | TypeCtor::FnPtr { .. } | ||
539 | | TypeCtor::Never | ||
540 | | TypeCtor::Closure { .. } => { | ||
541 | // other TypeCtors get interned and turned into a chalk StructId | ||
542 | let struct_id = db.intern_type_ctor(self).into(); | ||
543 | TypeName::Adt(struct_id) | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | |||
548 | fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor { | ||
549 | match type_name { | ||
550 | TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), | ||
551 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | ||
552 | TypeName::OpaqueType(_) => unreachable!(), | ||
553 | |||
554 | TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, | ||
555 | TypeName::Scalar(Scalar::Char) => TypeCtor::Char, | ||
556 | TypeName::Scalar(Scalar::Int(int_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { | ||
557 | signedness: Signedness::Signed, | ||
558 | bitness: bitness_from_chalk_int(int_ty), | ||
559 | })), | ||
560 | TypeName::Scalar(Scalar::Uint(uint_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { | ||
561 | signedness: Signedness::Unsigned, | ||
562 | bitness: bitness_from_chalk_uint(uint_ty), | ||
563 | })), | ||
564 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => { | ||
565 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) | ||
566 | } | ||
567 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => { | ||
568 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) | ||
569 | } | ||
570 | TypeName::Tuple(cardinality) => TypeCtor::Tuple { cardinality: cardinality as u16 }, | ||
571 | TypeName::Raw(mutability) => TypeCtor::RawPtr(from_chalk(db, mutability)), | ||
572 | TypeName::Slice => TypeCtor::Slice, | ||
573 | TypeName::Ref(mutability) => TypeCtor::Ref(from_chalk(db, mutability)), | ||
574 | TypeName::Str => TypeCtor::Str, | ||
575 | |||
576 | TypeName::FnDef(_) => unreachable!(), | ||
577 | |||
578 | TypeName::Error => { | ||
579 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor | ||
580 | unreachable!() | ||
581 | } | ||
582 | } | ||
583 | } | ||
584 | } | ||
585 | |||
586 | fn bitness_from_chalk_uint(uint_ty: chalk_ir::UintTy) -> IntBitness { | ||
587 | use chalk_ir::UintTy; | ||
588 | |||
589 | match uint_ty { | ||
590 | UintTy::Usize => IntBitness::Xsize, | ||
591 | UintTy::U8 => IntBitness::X8, | ||
592 | UintTy::U16 => IntBitness::X16, | ||
593 | UintTy::U32 => IntBitness::X32, | ||
594 | UintTy::U64 => IntBitness::X64, | ||
595 | UintTy::U128 => IntBitness::X128, | ||
596 | } | ||
597 | } | ||
598 | |||
599 | fn bitness_from_chalk_int(int_ty: chalk_ir::IntTy) -> IntBitness { | ||
600 | use chalk_ir::IntTy; | ||
601 | |||
602 | match int_ty { | ||
603 | IntTy::Isize => IntBitness::Xsize, | ||
604 | IntTy::I8 => IntBitness::X8, | ||
605 | IntTy::I16 => IntBitness::X16, | ||
606 | IntTy::I32 => IntBitness::X32, | ||
607 | IntTy::I64 => IntBitness::X64, | ||
608 | IntTy::I128 => IntBitness::X128, | ||
609 | } | ||
610 | } | ||
611 | |||
612 | fn int_ty_to_chalk(int_ty: IntTy) -> Scalar { | ||
613 | use chalk_ir::{IntTy, UintTy}; | ||
614 | |||
615 | match int_ty.signedness { | ||
616 | Signedness::Signed => Scalar::Int(match int_ty.bitness { | ||
617 | IntBitness::Xsize => IntTy::Isize, | ||
618 | IntBitness::X8 => IntTy::I8, | ||
619 | IntBitness::X16 => IntTy::I16, | ||
620 | IntBitness::X32 => IntTy::I32, | ||
621 | IntBitness::X64 => IntTy::I64, | ||
622 | IntBitness::X128 => IntTy::I128, | ||
623 | }), | ||
624 | Signedness::Unsigned => Scalar::Uint(match int_ty.bitness { | ||
625 | IntBitness::Xsize => UintTy::Usize, | ||
626 | IntBitness::X8 => UintTy::U8, | ||
627 | IntBitness::X16 => UintTy::U16, | ||
628 | IntBitness::X32 => UintTy::U32, | ||
629 | IntBitness::X64 => UintTy::U64, | ||
630 | IntBitness::X128 => UintTy::U128, | ||
631 | }), | ||
632 | } | ||
633 | } | ||
634 | |||
635 | impl ToChalk for Mutability { | ||
636 | type Chalk = chalk_ir::Mutability; | ||
637 | fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk { | ||
638 | match self { | ||
639 | Mutability::Shared => chalk_ir::Mutability::Not, | ||
640 | Mutability::Mut => chalk_ir::Mutability::Mut, | ||
641 | } | ||
642 | } | ||
643 | fn from_chalk(_db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
644 | match chalk { | ||
645 | chalk_ir::Mutability::Mut => Mutability::Mut, | ||
646 | chalk_ir::Mutability::Not => Mutability::Shared, | ||
647 | } | ||
648 | } | ||
649 | } | ||
650 | |||
651 | impl ToChalk for Impl { | ||
652 | type Chalk = ImplId; | ||
653 | |||
654 | fn to_chalk(self, db: &dyn HirDatabase) -> ImplId { | ||
655 | db.intern_chalk_impl(self).into() | ||
656 | } | ||
657 | |||
658 | fn from_chalk(db: &dyn HirDatabase, impl_id: ImplId) -> Impl { | ||
659 | db.lookup_intern_chalk_impl(impl_id.into()) | ||
660 | } | ||
661 | } | ||
662 | |||
663 | impl ToChalk for TypeAliasId { | ||
664 | type Chalk = AssocTypeId; | ||
665 | |||
666 | fn to_chalk(self, _db: &dyn HirDatabase) -> AssocTypeId { | ||
667 | chalk_ir::AssocTypeId(self.as_intern_id()) | ||
668 | } | ||
669 | |||
670 | fn from_chalk(_db: &dyn HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { | ||
671 | InternKey::from_intern_id(type_alias_id.0) | ||
672 | } | ||
673 | } | ||
674 | |||
675 | impl ToChalk for AssocTyValue { | ||
676 | type Chalk = AssociatedTyValueId; | ||
677 | |||
678 | fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValueId { | ||
679 | db.intern_assoc_ty_value(self).into() | ||
680 | } | ||
681 | |||
682 | fn from_chalk(db: &dyn HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { | ||
683 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
684 | } | ||
685 | } | ||
686 | |||
687 | impl ToChalk for GenericPredicate { | ||
688 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | ||
689 | |||
690 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | ||
691 | match self { | ||
692 | GenericPredicate::Implemented(trait_ref) => { | ||
693 | let chalk_trait_ref = trait_ref.to_chalk(db); | ||
694 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | ||
695 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | ||
696 | } | ||
697 | GenericPredicate::Projection(projection_pred) => { | ||
698 | let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); | ||
699 | let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); | ||
700 | let alias = chalk_ir::AliasTy::Projection(projection); | ||
701 | make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) | ||
702 | } | ||
703 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), | ||
704 | } | ||
705 | } | ||
706 | |||
707 | fn from_chalk( | ||
708 | db: &dyn HirDatabase, | ||
709 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | ||
710 | ) -> GenericPredicate { | ||
711 | // we don't produce any where clauses with binders and can't currently deal with them | ||
712 | match where_clause | ||
713 | .skip_binders() | ||
714 | .shifted_out(&Interner) | ||
715 | .expect("unexpected bound vars in where clause") | ||
716 | { | ||
717 | chalk_ir::WhereClause::Implemented(tr) => { | ||
718 | GenericPredicate::Implemented(from_chalk(db, tr)) | ||
719 | } | ||
720 | chalk_ir::WhereClause::AliasEq(projection_eq) => { | ||
721 | let projection_ty = from_chalk( | ||
722 | db, | ||
723 | match projection_eq.alias { | ||
724 | chalk_ir::AliasTy::Projection(p) => p, | ||
725 | _ => unimplemented!(), | ||
726 | }, | ||
727 | ); | ||
728 | let ty = from_chalk(db, projection_eq.ty); | ||
729 | GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) | ||
730 | } | ||
731 | } | ||
732 | } | ||
733 | } | ||
734 | |||
735 | impl ToChalk for ProjectionTy { | ||
736 | type Chalk = chalk_ir::ProjectionTy<Interner>; | ||
737 | |||
738 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> { | ||
739 | chalk_ir::ProjectionTy { | ||
740 | associated_ty_id: self.associated_ty.to_chalk(db), | ||
741 | substitution: self.parameters.to_chalk(db), | ||
742 | } | ||
743 | } | ||
744 | |||
745 | fn from_chalk( | ||
746 | db: &dyn HirDatabase, | ||
747 | projection_ty: chalk_ir::ProjectionTy<Interner>, | ||
748 | ) -> ProjectionTy { | ||
749 | ProjectionTy { | ||
750 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | ||
751 | parameters: from_chalk(db, projection_ty.substitution), | ||
752 | } | ||
753 | } | ||
754 | } | ||
755 | |||
756 | impl ToChalk for super::ProjectionPredicate { | ||
757 | type Chalk = chalk_ir::AliasEq<Interner>; | ||
758 | |||
759 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { | ||
760 | chalk_ir::AliasEq { | ||
761 | alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)), | ||
762 | ty: self.ty.to_chalk(db), | ||
763 | } | ||
764 | } | ||
765 | |||
766 | fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { | ||
767 | unimplemented!() | ||
768 | } | ||
769 | } | ||
770 | |||
771 | impl ToChalk for Obligation { | ||
772 | type Chalk = chalk_ir::DomainGoal<Interner>; | ||
773 | |||
774 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { | ||
775 | match self { | ||
776 | Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), | ||
777 | Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner), | ||
778 | } | ||
779 | } | ||
780 | |||
781 | fn from_chalk(_db: &dyn HirDatabase, _goal: chalk_ir::DomainGoal<Interner>) -> Self { | ||
782 | unimplemented!() | ||
783 | } | ||
784 | } | ||
785 | |||
786 | impl<T> ToChalk for Canonical<T> | ||
787 | where | ||
788 | T: ToChalk, | ||
789 | T::Chalk: HasInterner<Interner = Interner>, | ||
790 | { | ||
791 | type Chalk = chalk_ir::Canonical<T::Chalk>; | ||
792 | |||
793 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | ||
794 | let parameter = chalk_ir::CanonicalVarKind::new( | ||
795 | chalk_ir::VariableKind::Ty, | ||
796 | chalk_ir::UniverseIndex::ROOT, | ||
797 | ); | ||
798 | let value = self.value.to_chalk(db); | ||
799 | chalk_ir::Canonical { | ||
800 | value, | ||
801 | binders: chalk_ir::CanonicalVarKinds::from(&Interner, vec![parameter; self.num_vars]), | ||
802 | } | ||
803 | } | ||
804 | |||
805 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | ||
806 | Canonical { | ||
807 | num_vars: canonical.binders.len(&Interner), | ||
808 | value: from_chalk(db, canonical.value), | ||
809 | } | ||
810 | } | ||
811 | } | ||
812 | |||
813 | impl ToChalk for Arc<super::TraitEnvironment> { | ||
814 | type Chalk = chalk_ir::Environment<Interner>; | ||
815 | |||
816 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Environment<Interner> { | ||
817 | let mut clauses = Vec::new(); | ||
818 | for pred in &self.predicates { | ||
819 | if pred.is_error() { | ||
820 | // for env, we just ignore errors | ||
821 | continue; | ||
822 | } | ||
823 | let program_clause: chalk_ir::ProgramClause<Interner> = | ||
824 | pred.clone().to_chalk(db).cast(&Interner); | ||
825 | clauses.push(program_clause.into_from_env_clause(&Interner)); | ||
826 | } | ||
827 | chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses) | ||
828 | } | ||
829 | |||
830 | fn from_chalk( | ||
831 | _db: &dyn HirDatabase, | ||
832 | _env: chalk_ir::Environment<Interner>, | ||
833 | ) -> Arc<super::TraitEnvironment> { | ||
834 | unimplemented!() | ||
835 | } | ||
836 | } | ||
837 | |||
838 | impl<T: ToChalk> ToChalk for super::InEnvironment<T> | ||
839 | where | ||
840 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
841 | { | ||
842 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | ||
843 | |||
844 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | ||
845 | chalk_ir::InEnvironment { | ||
846 | environment: self.environment.to_chalk(db), | ||
847 | goal: self.value.to_chalk(db), | ||
848 | } | ||
849 | } | ||
850 | |||
851 | fn from_chalk( | ||
852 | db: &dyn HirDatabase, | ||
853 | in_env: chalk_ir::InEnvironment<T::Chalk>, | ||
854 | ) -> super::InEnvironment<T> { | ||
855 | super::InEnvironment { | ||
856 | environment: from_chalk(db, in_env.environment), | ||
857 | value: from_chalk(db, in_env.goal), | ||
858 | } | ||
859 | } | ||
860 | } | ||
861 | |||
862 | impl ToChalk for builtin::BuiltinImplData { | ||
863 | type Chalk = ImplDatum; | ||
864 | |||
865 | fn to_chalk(self, db: &dyn HirDatabase) -> ImplDatum { | ||
866 | let impl_type = chalk_rust_ir::ImplType::External; | ||
867 | let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); | ||
868 | |||
869 | let impl_datum_bound = | ||
870 | chalk_rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses }; | ||
871 | let associated_ty_value_ids = | ||
872 | self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect(); | ||
873 | chalk_rust_ir::ImplDatum { | ||
874 | binders: make_binders(impl_datum_bound, self.num_vars), | ||
875 | impl_type, | ||
876 | polarity: chalk_rust_ir::Polarity::Positive, | ||
877 | associated_ty_value_ids, | ||
878 | } | ||
879 | } | ||
880 | |||
881 | fn from_chalk(_db: &dyn HirDatabase, _data: ImplDatum) -> Self { | ||
882 | unimplemented!() | ||
883 | } | ||
884 | } | ||
885 | |||
886 | impl ToChalk for builtin::BuiltinImplAssocTyValueData { | ||
887 | type Chalk = AssociatedTyValue; | ||
888 | |||
889 | fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue { | ||
890 | let ty = self.value.to_chalk(db); | ||
891 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty }; | ||
892 | |||
893 | chalk_rust_ir::AssociatedTyValue { | ||
894 | associated_ty_id: self.assoc_ty_id.to_chalk(db), | ||
895 | impl_id: self.impl_.to_chalk(db), | ||
896 | value: make_binders(value_bound, self.num_vars), | ||
897 | } | ||
898 | } | ||
899 | |||
900 | fn from_chalk( | ||
901 | _db: &dyn HirDatabase, | ||
902 | _data: AssociatedTyValue, | ||
903 | ) -> builtin::BuiltinImplAssocTyValueData { | ||
904 | unimplemented!() | ||
905 | } | ||
906 | } | ||
907 | |||
908 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | ||
909 | where | ||
910 | T: HasInterner<Interner = Interner>, | ||
911 | { | ||
912 | chalk_ir::Binders::new( | ||
913 | chalk_ir::VariableKinds::from( | ||
914 | &Interner, | ||
915 | std::iter::repeat(chalk_ir::VariableKind::Ty).take(num_vars), | ||
916 | ), | ||
917 | value, | ||
918 | ) | ||
919 | } | ||
920 | |||
921 | fn convert_where_clauses( | ||
922 | db: &dyn HirDatabase, | ||
923 | def: GenericDefId, | ||
924 | substs: &Substs, | ||
925 | ) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> { | ||
926 | let generic_predicates = db.generic_predicates(def); | ||
927 | let mut result = Vec::with_capacity(generic_predicates.len()); | ||
928 | for pred in generic_predicates.iter() { | ||
929 | if pred.value.is_error() { | ||
930 | // skip errored predicates completely | ||
931 | continue; | ||
932 | } | ||
933 | result.push(pred.clone().subst(substs).to_chalk(db)); | ||
934 | } | ||
935 | result | ||
936 | } | ||
937 | |||
938 | fn generic_predicate_to_inline_bound( | ||
939 | db: &dyn HirDatabase, | ||
940 | pred: &GenericPredicate, | ||
941 | self_ty: &Ty, | ||
942 | ) -> Option<chalk_rust_ir::InlineBound<Interner>> { | ||
943 | // An InlineBound is like a GenericPredicate, except the self type is left out. | ||
944 | // We don't have a special type for this, but Chalk does. | ||
945 | match pred { | ||
946 | GenericPredicate::Implemented(trait_ref) => { | ||
947 | if &trait_ref.substs[0] != self_ty { | ||
948 | // we can only convert predicates back to type bounds if they | ||
949 | // have the expected self type | ||
950 | return None; | ||
951 | } | ||
952 | let args_no_self = trait_ref.substs[1..] | ||
953 | .iter() | ||
954 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | ||
955 | .collect(); | ||
956 | let trait_bound = | ||
957 | chalk_rust_ir::TraitBound { trait_id: trait_ref.trait_.to_chalk(db), args_no_self }; | ||
958 | Some(chalk_rust_ir::InlineBound::TraitBound(trait_bound)) | ||
959 | } | ||
960 | GenericPredicate::Projection(proj) => { | ||
961 | if &proj.projection_ty.parameters[0] != self_ty { | ||
962 | return None; | ||
963 | } | ||
964 | let trait_ = match proj.projection_ty.associated_ty.lookup(db.upcast()).container { | ||
965 | AssocContainerId::TraitId(t) => t, | ||
966 | _ => panic!("associated type not in trait"), | ||
967 | }; | ||
968 | let args_no_self = proj.projection_ty.parameters[1..] | ||
969 | .iter() | ||
970 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | ||
971 | .collect(); | ||
972 | let alias_eq_bound = chalk_rust_ir::AliasEqBound { | ||
973 | value: proj.ty.clone().to_chalk(db), | ||
974 | trait_bound: chalk_rust_ir::TraitBound { | ||
975 | trait_id: trait_.to_chalk(db), | ||
976 | args_no_self, | ||
977 | }, | ||
978 | associated_ty_id: proj.projection_ty.associated_ty.to_chalk(db), | ||
979 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | ||
980 | }; | ||
981 | Some(chalk_rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | ||
982 | } | ||
983 | GenericPredicate::Error => None, | ||
984 | } | ||
985 | } | ||
986 | |||
987 | impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | 41 | impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { |
988 | fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { | 42 | fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { |
989 | self.db.associated_ty_data(id) | 43 | self.db.associated_ty_data(id) |
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs new file mode 100644 index 000000000..032deca75 --- /dev/null +++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs | |||
@@ -0,0 +1,298 @@ | |||
1 | //! Implementation of the Chalk `Interner` trait, which allows customizing the | ||
2 | //! representation of the various objects Chalk deals with (types, goals etc.). | ||
3 | |||
4 | use super::tls; | ||
5 | use chalk_ir::{GenericArg, Goal, GoalData}; | ||
6 | use hir_def::TypeAliasId; | ||
7 | use ra_db::salsa::InternId; | ||
8 | use std::{fmt, sync::Arc}; | ||
9 | |||
10 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] | ||
11 | pub struct Interner; | ||
12 | |||
13 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | ||
14 | pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<Interner>; | ||
15 | pub type TraitId = chalk_ir::TraitId<Interner>; | ||
16 | pub type TraitDatum = chalk_rust_ir::TraitDatum<Interner>; | ||
17 | pub type StructId = chalk_ir::AdtId<Interner>; | ||
18 | pub type StructDatum = chalk_rust_ir::AdtDatum<Interner>; | ||
19 | pub type ImplId = chalk_ir::ImplId<Interner>; | ||
20 | pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>; | ||
21 | pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>; | ||
22 | pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>; | ||
23 | |||
24 | impl chalk_ir::interner::Interner for Interner { | ||
25 | type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? | ||
26 | type InternedLifetime = chalk_ir::LifetimeData<Self>; | ||
27 | type InternedConst = Arc<chalk_ir::ConstData<Self>>; | ||
28 | type InternedConcreteConst = (); | ||
29 | type InternedGenericArg = chalk_ir::GenericArgData<Self>; | ||
30 | type InternedGoal = Arc<GoalData<Self>>; | ||
31 | type InternedGoals = Vec<Goal<Self>>; | ||
32 | type InternedSubstitution = Vec<GenericArg<Self>>; | ||
33 | type InternedProgramClause = chalk_ir::ProgramClauseData<Self>; | ||
34 | type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; | ||
35 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; | ||
36 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; | ||
37 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; | ||
38 | type DefId = InternId; | ||
39 | type InternedAdtId = InternId; | ||
40 | type Identifier = TypeAliasId; | ||
41 | |||
42 | fn debug_adt_id(type_kind_id: StructId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
43 | tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) | ||
44 | } | ||
45 | |||
46 | fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
47 | tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) | ||
48 | } | ||
49 | |||
50 | fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
51 | tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) | ||
52 | } | ||
53 | |||
54 | fn debug_alias( | ||
55 | alias: &chalk_ir::AliasTy<Interner>, | ||
56 | fmt: &mut fmt::Formatter<'_>, | ||
57 | ) -> Option<fmt::Result> { | ||
58 | tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) | ||
59 | } | ||
60 | |||
61 | fn debug_projection_ty( | ||
62 | proj: &chalk_ir::ProjectionTy<Interner>, | ||
63 | fmt: &mut fmt::Formatter<'_>, | ||
64 | ) -> Option<fmt::Result> { | ||
65 | tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) | ||
66 | } | ||
67 | |||
68 | fn debug_opaque_ty( | ||
69 | opaque_ty: &chalk_ir::OpaqueTy<Interner>, | ||
70 | fmt: &mut fmt::Formatter<'_>, | ||
71 | ) -> Option<fmt::Result> { | ||
72 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt))) | ||
73 | } | ||
74 | |||
75 | fn debug_opaque_ty_id( | ||
76 | opaque_ty_id: chalk_ir::OpaqueTyId<Self>, | ||
77 | fmt: &mut fmt::Formatter<'_>, | ||
78 | ) -> Option<fmt::Result> { | ||
79 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt))) | ||
80 | } | ||
81 | |||
82 | fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
83 | tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) | ||
84 | } | ||
85 | |||
86 | fn debug_lifetime( | ||
87 | lifetime: &chalk_ir::Lifetime<Interner>, | ||
88 | fmt: &mut fmt::Formatter<'_>, | ||
89 | ) -> Option<fmt::Result> { | ||
90 | tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt))) | ||
91 | } | ||
92 | |||
93 | fn debug_generic_arg( | ||
94 | parameter: &GenericArg<Interner>, | ||
95 | fmt: &mut fmt::Formatter<'_>, | ||
96 | ) -> Option<fmt::Result> { | ||
97 | tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) | ||
98 | } | ||
99 | |||
100 | fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
101 | tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt))) | ||
102 | } | ||
103 | |||
104 | fn debug_goals( | ||
105 | goals: &chalk_ir::Goals<Interner>, | ||
106 | fmt: &mut fmt::Formatter<'_>, | ||
107 | ) -> Option<fmt::Result> { | ||
108 | tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt))) | ||
109 | } | ||
110 | |||
111 | fn debug_program_clause_implication( | ||
112 | pci: &chalk_ir::ProgramClauseImplication<Interner>, | ||
113 | fmt: &mut fmt::Formatter<'_>, | ||
114 | ) -> Option<fmt::Result> { | ||
115 | tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt))) | ||
116 | } | ||
117 | |||
118 | fn debug_application_ty( | ||
119 | application_ty: &chalk_ir::ApplicationTy<Interner>, | ||
120 | fmt: &mut fmt::Formatter<'_>, | ||
121 | ) -> Option<fmt::Result> { | ||
122 | tls::with_current_program(|prog| Some(prog?.debug_application_ty(application_ty, fmt))) | ||
123 | } | ||
124 | |||
125 | fn debug_substitution( | ||
126 | substitution: &chalk_ir::Substitution<Interner>, | ||
127 | fmt: &mut fmt::Formatter<'_>, | ||
128 | ) -> Option<fmt::Result> { | ||
129 | tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt))) | ||
130 | } | ||
131 | |||
132 | fn debug_separator_trait_ref( | ||
133 | separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>, | ||
134 | fmt: &mut fmt::Formatter<'_>, | ||
135 | ) -> Option<fmt::Result> { | ||
136 | tls::with_current_program(|prog| { | ||
137 | Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt)) | ||
138 | }) | ||
139 | } | ||
140 | |||
141 | fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { | ||
142 | Box::new(ty) | ||
143 | } | ||
144 | |||
145 | fn ty_data<'a>(&self, ty: &'a Box<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> { | ||
146 | ty | ||
147 | } | ||
148 | |||
149 | fn intern_lifetime( | ||
150 | &self, | ||
151 | lifetime: chalk_ir::LifetimeData<Self>, | ||
152 | ) -> chalk_ir::LifetimeData<Self> { | ||
153 | lifetime | ||
154 | } | ||
155 | |||
156 | fn lifetime_data<'a>( | ||
157 | &self, | ||
158 | lifetime: &'a chalk_ir::LifetimeData<Self>, | ||
159 | ) -> &'a chalk_ir::LifetimeData<Self> { | ||
160 | lifetime | ||
161 | } | ||
162 | |||
163 | fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Arc<chalk_ir::ConstData<Self>> { | ||
164 | Arc::new(constant) | ||
165 | } | ||
166 | |||
167 | fn const_data<'a>( | ||
168 | &self, | ||
169 | constant: &'a Arc<chalk_ir::ConstData<Self>>, | ||
170 | ) -> &'a chalk_ir::ConstData<Self> { | ||
171 | constant | ||
172 | } | ||
173 | |||
174 | fn const_eq(&self, _ty: &Box<chalk_ir::TyData<Self>>, _c1: &(), _c2: &()) -> bool { | ||
175 | true | ||
176 | } | ||
177 | |||
178 | fn intern_generic_arg( | ||
179 | &self, | ||
180 | parameter: chalk_ir::GenericArgData<Self>, | ||
181 | ) -> chalk_ir::GenericArgData<Self> { | ||
182 | parameter | ||
183 | } | ||
184 | |||
185 | fn generic_arg_data<'a>( | ||
186 | &self, | ||
187 | parameter: &'a chalk_ir::GenericArgData<Self>, | ||
188 | ) -> &'a chalk_ir::GenericArgData<Self> { | ||
189 | parameter | ||
190 | } | ||
191 | |||
192 | fn intern_goal(&self, goal: GoalData<Self>) -> Arc<GoalData<Self>> { | ||
193 | Arc::new(goal) | ||
194 | } | ||
195 | |||
196 | fn intern_goals<E>( | ||
197 | &self, | ||
198 | data: impl IntoIterator<Item = Result<Goal<Self>, E>>, | ||
199 | ) -> Result<Self::InternedGoals, E> { | ||
200 | data.into_iter().collect() | ||
201 | } | ||
202 | |||
203 | fn goal_data<'a>(&self, goal: &'a Arc<GoalData<Self>>) -> &'a GoalData<Self> { | ||
204 | goal | ||
205 | } | ||
206 | |||
207 | fn goals_data<'a>(&self, goals: &'a Vec<Goal<Interner>>) -> &'a [Goal<Interner>] { | ||
208 | goals | ||
209 | } | ||
210 | |||
211 | fn intern_substitution<E>( | ||
212 | &self, | ||
213 | data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>, | ||
214 | ) -> Result<Vec<GenericArg<Self>>, E> { | ||
215 | data.into_iter().collect() | ||
216 | } | ||
217 | |||
218 | fn substitution_data<'a>( | ||
219 | &self, | ||
220 | substitution: &'a Vec<GenericArg<Self>>, | ||
221 | ) -> &'a [GenericArg<Self>] { | ||
222 | substitution | ||
223 | } | ||
224 | |||
225 | fn intern_program_clause( | ||
226 | &self, | ||
227 | data: chalk_ir::ProgramClauseData<Self>, | ||
228 | ) -> chalk_ir::ProgramClauseData<Self> { | ||
229 | data | ||
230 | } | ||
231 | |||
232 | fn program_clause_data<'a>( | ||
233 | &self, | ||
234 | clause: &'a chalk_ir::ProgramClauseData<Self>, | ||
235 | ) -> &'a chalk_ir::ProgramClauseData<Self> { | ||
236 | clause | ||
237 | } | ||
238 | |||
239 | fn intern_program_clauses<E>( | ||
240 | &self, | ||
241 | data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>, | ||
242 | ) -> Result<Arc<[chalk_ir::ProgramClause<Self>]>, E> { | ||
243 | data.into_iter().collect() | ||
244 | } | ||
245 | |||
246 | fn program_clauses_data<'a>( | ||
247 | &self, | ||
248 | clauses: &'a Arc<[chalk_ir::ProgramClause<Self>]>, | ||
249 | ) -> &'a [chalk_ir::ProgramClause<Self>] { | ||
250 | &clauses | ||
251 | } | ||
252 | |||
253 | fn intern_quantified_where_clauses<E>( | ||
254 | &self, | ||
255 | data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>, | ||
256 | ) -> Result<Self::InternedQuantifiedWhereClauses, E> { | ||
257 | data.into_iter().collect() | ||
258 | } | ||
259 | |||
260 | fn quantified_where_clauses_data<'a>( | ||
261 | &self, | ||
262 | clauses: &'a Self::InternedQuantifiedWhereClauses, | ||
263 | ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] { | ||
264 | clauses | ||
265 | } | ||
266 | |||
267 | fn intern_generic_arg_kinds<E>( | ||
268 | &self, | ||
269 | data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>, | ||
270 | ) -> Result<Self::InternedVariableKinds, E> { | ||
271 | data.into_iter().collect() | ||
272 | } | ||
273 | |||
274 | fn variable_kinds_data<'a>( | ||
275 | &self, | ||
276 | parameter_kinds: &'a Self::InternedVariableKinds, | ||
277 | ) -> &'a [chalk_ir::VariableKind<Self>] { | ||
278 | ¶meter_kinds | ||
279 | } | ||
280 | |||
281 | fn intern_canonical_var_kinds<E>( | ||
282 | &self, | ||
283 | data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>, | ||
284 | ) -> Result<Self::InternedCanonicalVarKinds, E> { | ||
285 | data.into_iter().collect() | ||
286 | } | ||
287 | |||
288 | fn canonical_var_kinds_data<'a>( | ||
289 | &self, | ||
290 | canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, | ||
291 | ) -> &'a [chalk_ir::CanonicalVarKind<Self>] { | ||
292 | &canonical_var_kinds | ||
293 | } | ||
294 | } | ||
295 | |||
296 | impl chalk_ir::interner::HasInterner for Interner { | ||
297 | type Interner = Self; | ||
298 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs new file mode 100644 index 000000000..a83d82fd8 --- /dev/null +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs | |||
@@ -0,0 +1,672 @@ | |||
1 | //! This module contains the implementations of the `ToChalk` trait, which | ||
2 | //! handles conversion between our data types and their corresponding types in | ||
3 | //! Chalk (in both directions); plus some helper functions for more specialized | ||
4 | //! conversions. | ||
5 | |||
6 | use chalk_ir::{ | ||
7 | cast::Cast, fold::shift::Shift, interner::HasInterner, PlaceholderIndex, Scalar, TypeName, | ||
8 | UniverseIndex, | ||
9 | }; | ||
10 | |||
11 | use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | ||
12 | use ra_db::salsa::InternKey; | ||
13 | |||
14 | use crate::{ | ||
15 | db::HirDatabase, | ||
16 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, | ||
17 | traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, | ||
18 | ApplicationTy, GenericPredicate, InEnvironment, ProjectionPredicate, ProjectionTy, Substs, | ||
19 | TraitEnvironment, TraitRef, Ty, TypeCtor, | ||
20 | }; | ||
21 | |||
22 | use super::interner::*; | ||
23 | use super::*; | ||
24 | |||
25 | impl ToChalk for Ty { | ||
26 | type Chalk = chalk_ir::Ty<Interner>; | ||
27 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { | ||
28 | match self { | ||
29 | Ty::Apply(apply_ty) => { | ||
30 | if let TypeCtor::Ref(m) = apply_ty.ctor { | ||
31 | return ref_to_chalk(db, m, apply_ty.parameters); | ||
32 | } | ||
33 | let name = apply_ty.ctor.to_chalk(db); | ||
34 | let substitution = apply_ty.parameters.to_chalk(db); | ||
35 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | ||
36 | } | ||
37 | Ty::Projection(proj_ty) => { | ||
38 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | ||
39 | let substitution = proj_ty.parameters.to_chalk(db); | ||
40 | chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { | ||
41 | associated_ty_id, | ||
42 | substitution, | ||
43 | }) | ||
44 | .cast(&Interner) | ||
45 | .intern(&Interner) | ||
46 | } | ||
47 | Ty::Placeholder(id) => { | ||
48 | let interned_id = db.intern_type_param_id(id); | ||
49 | PlaceholderIndex { | ||
50 | ui: UniverseIndex::ROOT, | ||
51 | idx: interned_id.as_intern_id().as_usize(), | ||
52 | } | ||
53 | .to_ty::<Interner>(&Interner) | ||
54 | } | ||
55 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), | ||
56 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | ||
57 | Ty::Dyn(predicates) => { | ||
58 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from( | ||
59 | &Interner, | ||
60 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), | ||
61 | ); | ||
62 | let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; | ||
63 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) | ||
64 | } | ||
65 | Ty::Opaque(_) | Ty::Unknown => { | ||
66 | let substitution = chalk_ir::Substitution::empty(&Interner); | ||
67 | let name = TypeName::Error; | ||
68 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { | ||
73 | match chalk.data(&Interner).clone() { | ||
74 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { | ||
75 | TypeName::Error => Ty::Unknown, | ||
76 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), | ||
77 | _ => { | ||
78 | let ctor = from_chalk(db, apply_ty.name); | ||
79 | let parameters = from_chalk(db, apply_ty.substitution); | ||
80 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
81 | } | ||
82 | }, | ||
83 | chalk_ir::TyData::Placeholder(idx) => { | ||
84 | assert_eq!(idx.ui, UniverseIndex::ROOT); | ||
85 | let interned_id = crate::db::GlobalTypeParamId::from_intern_id( | ||
86 | crate::salsa::InternId::from(idx.idx), | ||
87 | ); | ||
88 | Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) | ||
89 | } | ||
90 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => { | ||
91 | let associated_ty = from_chalk(db, proj.associated_ty_id); | ||
92 | let parameters = from_chalk(db, proj.substitution); | ||
93 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | ||
94 | } | ||
95 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), | ||
96 | chalk_ir::TyData::Function(_) => unimplemented!(), | ||
97 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx), | ||
98 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, | ||
99 | chalk_ir::TyData::Dyn(where_clauses) => { | ||
100 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); | ||
101 | let predicates = where_clauses | ||
102 | .bounds | ||
103 | .skip_binders() | ||
104 | .iter(&Interner) | ||
105 | .map(|c| from_chalk(db, c.clone())) | ||
106 | .collect(); | ||
107 | Ty::Dyn(predicates) | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | const LIFETIME_PLACEHOLDER: PlaceholderIndex = | ||
114 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; | ||
115 | |||
116 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a | ||
117 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. | ||
118 | fn ref_to_chalk( | ||
119 | db: &dyn HirDatabase, | ||
120 | mutability: Mutability, | ||
121 | subst: Substs, | ||
122 | ) -> chalk_ir::Ty<Interner> { | ||
123 | let arg = subst[0].clone().to_chalk(db); | ||
124 | let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); | ||
125 | chalk_ir::ApplicationTy { | ||
126 | name: TypeName::Ref(mutability.to_chalk(db)), | ||
127 | substitution: chalk_ir::Substitution::from( | ||
128 | &Interner, | ||
129 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], | ||
130 | ), | ||
131 | } | ||
132 | .intern(&Interner) | ||
133 | } | ||
134 | |||
135 | /// Here we remove the lifetime from the type we got from Chalk. | ||
136 | fn ref_from_chalk( | ||
137 | db: &dyn HirDatabase, | ||
138 | mutability: chalk_ir::Mutability, | ||
139 | subst: chalk_ir::Substitution<Interner>, | ||
140 | ) -> Ty { | ||
141 | let tys = subst | ||
142 | .iter(&Interner) | ||
143 | .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone()))) | ||
144 | .collect(); | ||
145 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) | ||
146 | } | ||
147 | |||
148 | impl ToChalk for Substs { | ||
149 | type Chalk = chalk_ir::Substitution<Interner>; | ||
150 | |||
151 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { | ||
152 | chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) | ||
153 | } | ||
154 | |||
155 | fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { | ||
156 | let tys = parameters | ||
157 | .iter(&Interner) | ||
158 | .map(|p| match p.ty(&Interner) { | ||
159 | Some(ty) => from_chalk(db, ty.clone()), | ||
160 | None => unimplemented!(), | ||
161 | }) | ||
162 | .collect(); | ||
163 | Substs(tys) | ||
164 | } | ||
165 | } | ||
166 | |||
167 | impl ToChalk for TraitRef { | ||
168 | type Chalk = chalk_ir::TraitRef<Interner>; | ||
169 | |||
170 | fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> { | ||
171 | let trait_id = self.trait_.to_chalk(db); | ||
172 | let substitution = self.substs.to_chalk(db); | ||
173 | chalk_ir::TraitRef { trait_id, substitution } | ||
174 | } | ||
175 | |||
176 | fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self { | ||
177 | let trait_ = from_chalk(db, trait_ref.trait_id); | ||
178 | let substs = from_chalk(db, trait_ref.substitution); | ||
179 | TraitRef { trait_, substs } | ||
180 | } | ||
181 | } | ||
182 | |||
183 | impl ToChalk for hir_def::TraitId { | ||
184 | type Chalk = TraitId; | ||
185 | |||
186 | fn to_chalk(self, _db: &dyn HirDatabase) -> TraitId { | ||
187 | chalk_ir::TraitId(self.as_intern_id()) | ||
188 | } | ||
189 | |||
190 | fn from_chalk(_db: &dyn HirDatabase, trait_id: TraitId) -> hir_def::TraitId { | ||
191 | InternKey::from_intern_id(trait_id.0) | ||
192 | } | ||
193 | } | ||
194 | |||
195 | impl ToChalk for TypeCtor { | ||
196 | type Chalk = TypeName<Interner>; | ||
197 | |||
198 | fn to_chalk(self, db: &dyn HirDatabase) -> TypeName<Interner> { | ||
199 | match self { | ||
200 | TypeCtor::AssociatedType(type_alias) => { | ||
201 | let type_id = type_alias.to_chalk(db); | ||
202 | TypeName::AssociatedType(type_id) | ||
203 | } | ||
204 | |||
205 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), | ||
206 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), | ||
207 | TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), | ||
208 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) => { | ||
209 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) | ||
210 | } | ||
211 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) => { | ||
212 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) | ||
213 | } | ||
214 | |||
215 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), | ||
216 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), | ||
217 | TypeCtor::Slice => TypeName::Slice, | ||
218 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), | ||
219 | TypeCtor::Str => TypeName::Str, | ||
220 | TypeCtor::Int(Uncertain::Unknown) | ||
221 | | TypeCtor::Float(Uncertain::Unknown) | ||
222 | | TypeCtor::Adt(_) | ||
223 | | TypeCtor::Array | ||
224 | | TypeCtor::FnDef(_) | ||
225 | | TypeCtor::FnPtr { .. } | ||
226 | | TypeCtor::Never | ||
227 | | TypeCtor::Closure { .. } => { | ||
228 | // other TypeCtors get interned and turned into a chalk StructId | ||
229 | let struct_id = db.intern_type_ctor(self).into(); | ||
230 | TypeName::Adt(struct_id) | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | |||
235 | fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor { | ||
236 | match type_name { | ||
237 | TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), | ||
238 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | ||
239 | TypeName::OpaqueType(_) => unreachable!(), | ||
240 | |||
241 | TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, | ||
242 | TypeName::Scalar(Scalar::Char) => TypeCtor::Char, | ||
243 | TypeName::Scalar(Scalar::Int(int_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { | ||
244 | signedness: Signedness::Signed, | ||
245 | bitness: bitness_from_chalk_int(int_ty), | ||
246 | })), | ||
247 | TypeName::Scalar(Scalar::Uint(uint_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { | ||
248 | signedness: Signedness::Unsigned, | ||
249 | bitness: bitness_from_chalk_uint(uint_ty), | ||
250 | })), | ||
251 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => { | ||
252 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) | ||
253 | } | ||
254 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => { | ||
255 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) | ||
256 | } | ||
257 | TypeName::Tuple(cardinality) => TypeCtor::Tuple { cardinality: cardinality as u16 }, | ||
258 | TypeName::Raw(mutability) => TypeCtor::RawPtr(from_chalk(db, mutability)), | ||
259 | TypeName::Slice => TypeCtor::Slice, | ||
260 | TypeName::Ref(mutability) => TypeCtor::Ref(from_chalk(db, mutability)), | ||
261 | TypeName::Str => TypeCtor::Str, | ||
262 | |||
263 | TypeName::FnDef(_) => unreachable!(), | ||
264 | |||
265 | TypeName::Error => { | ||
266 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor | ||
267 | unreachable!() | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | } | ||
272 | |||
273 | fn bitness_from_chalk_uint(uint_ty: chalk_ir::UintTy) -> IntBitness { | ||
274 | use chalk_ir::UintTy; | ||
275 | |||
276 | match uint_ty { | ||
277 | UintTy::Usize => IntBitness::Xsize, | ||
278 | UintTy::U8 => IntBitness::X8, | ||
279 | UintTy::U16 => IntBitness::X16, | ||
280 | UintTy::U32 => IntBitness::X32, | ||
281 | UintTy::U64 => IntBitness::X64, | ||
282 | UintTy::U128 => IntBitness::X128, | ||
283 | } | ||
284 | } | ||
285 | |||
286 | fn bitness_from_chalk_int(int_ty: chalk_ir::IntTy) -> IntBitness { | ||
287 | use chalk_ir::IntTy; | ||
288 | |||
289 | match int_ty { | ||
290 | IntTy::Isize => IntBitness::Xsize, | ||
291 | IntTy::I8 => IntBitness::X8, | ||
292 | IntTy::I16 => IntBitness::X16, | ||
293 | IntTy::I32 => IntBitness::X32, | ||
294 | IntTy::I64 => IntBitness::X64, | ||
295 | IntTy::I128 => IntBitness::X128, | ||
296 | } | ||
297 | } | ||
298 | |||
299 | fn int_ty_to_chalk(int_ty: IntTy) -> Scalar { | ||
300 | use chalk_ir::{IntTy, UintTy}; | ||
301 | |||
302 | match int_ty.signedness { | ||
303 | Signedness::Signed => Scalar::Int(match int_ty.bitness { | ||
304 | IntBitness::Xsize => IntTy::Isize, | ||
305 | IntBitness::X8 => IntTy::I8, | ||
306 | IntBitness::X16 => IntTy::I16, | ||
307 | IntBitness::X32 => IntTy::I32, | ||
308 | IntBitness::X64 => IntTy::I64, | ||
309 | IntBitness::X128 => IntTy::I128, | ||
310 | }), | ||
311 | Signedness::Unsigned => Scalar::Uint(match int_ty.bitness { | ||
312 | IntBitness::Xsize => UintTy::Usize, | ||
313 | IntBitness::X8 => UintTy::U8, | ||
314 | IntBitness::X16 => UintTy::U16, | ||
315 | IntBitness::X32 => UintTy::U32, | ||
316 | IntBitness::X64 => UintTy::U64, | ||
317 | IntBitness::X128 => UintTy::U128, | ||
318 | }), | ||
319 | } | ||
320 | } | ||
321 | |||
322 | impl ToChalk for Mutability { | ||
323 | type Chalk = chalk_ir::Mutability; | ||
324 | fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk { | ||
325 | match self { | ||
326 | Mutability::Shared => chalk_ir::Mutability::Not, | ||
327 | Mutability::Mut => chalk_ir::Mutability::Mut, | ||
328 | } | ||
329 | } | ||
330 | fn from_chalk(_db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
331 | match chalk { | ||
332 | chalk_ir::Mutability::Mut => Mutability::Mut, | ||
333 | chalk_ir::Mutability::Not => Mutability::Shared, | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | |||
338 | impl ToChalk for Impl { | ||
339 | type Chalk = ImplId; | ||
340 | |||
341 | fn to_chalk(self, db: &dyn HirDatabase) -> ImplId { | ||
342 | db.intern_chalk_impl(self).into() | ||
343 | } | ||
344 | |||
345 | fn from_chalk(db: &dyn HirDatabase, impl_id: ImplId) -> Impl { | ||
346 | db.lookup_intern_chalk_impl(impl_id.into()) | ||
347 | } | ||
348 | } | ||
349 | |||
350 | impl ToChalk for TypeAliasId { | ||
351 | type Chalk = AssocTypeId; | ||
352 | |||
353 | fn to_chalk(self, _db: &dyn HirDatabase) -> AssocTypeId { | ||
354 | chalk_ir::AssocTypeId(self.as_intern_id()) | ||
355 | } | ||
356 | |||
357 | fn from_chalk(_db: &dyn HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { | ||
358 | InternKey::from_intern_id(type_alias_id.0) | ||
359 | } | ||
360 | } | ||
361 | |||
362 | impl ToChalk for AssocTyValue { | ||
363 | type Chalk = AssociatedTyValueId; | ||
364 | |||
365 | fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValueId { | ||
366 | db.intern_assoc_ty_value(self).into() | ||
367 | } | ||
368 | |||
369 | fn from_chalk(db: &dyn HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { | ||
370 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
371 | } | ||
372 | } | ||
373 | |||
374 | impl ToChalk for GenericPredicate { | ||
375 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | ||
376 | |||
377 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | ||
378 | match self { | ||
379 | GenericPredicate::Implemented(trait_ref) => { | ||
380 | let chalk_trait_ref = trait_ref.to_chalk(db); | ||
381 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | ||
382 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | ||
383 | } | ||
384 | GenericPredicate::Projection(projection_pred) => { | ||
385 | let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); | ||
386 | let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); | ||
387 | let alias = chalk_ir::AliasTy::Projection(projection); | ||
388 | make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) | ||
389 | } | ||
390 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), | ||
391 | } | ||
392 | } | ||
393 | |||
394 | fn from_chalk( | ||
395 | db: &dyn HirDatabase, | ||
396 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | ||
397 | ) -> GenericPredicate { | ||
398 | // we don't produce any where clauses with binders and can't currently deal with them | ||
399 | match where_clause | ||
400 | .skip_binders() | ||
401 | .shifted_out(&Interner) | ||
402 | .expect("unexpected bound vars in where clause") | ||
403 | { | ||
404 | chalk_ir::WhereClause::Implemented(tr) => { | ||
405 | GenericPredicate::Implemented(from_chalk(db, tr)) | ||
406 | } | ||
407 | chalk_ir::WhereClause::AliasEq(projection_eq) => { | ||
408 | let projection_ty = from_chalk( | ||
409 | db, | ||
410 | match projection_eq.alias { | ||
411 | chalk_ir::AliasTy::Projection(p) => p, | ||
412 | _ => unimplemented!(), | ||
413 | }, | ||
414 | ); | ||
415 | let ty = from_chalk(db, projection_eq.ty); | ||
416 | GenericPredicate::Projection(ProjectionPredicate { projection_ty, ty }) | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | impl ToChalk for ProjectionTy { | ||
423 | type Chalk = chalk_ir::ProjectionTy<Interner>; | ||
424 | |||
425 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> { | ||
426 | chalk_ir::ProjectionTy { | ||
427 | associated_ty_id: self.associated_ty.to_chalk(db), | ||
428 | substitution: self.parameters.to_chalk(db), | ||
429 | } | ||
430 | } | ||
431 | |||
432 | fn from_chalk( | ||
433 | db: &dyn HirDatabase, | ||
434 | projection_ty: chalk_ir::ProjectionTy<Interner>, | ||
435 | ) -> ProjectionTy { | ||
436 | ProjectionTy { | ||
437 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | ||
438 | parameters: from_chalk(db, projection_ty.substitution), | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
443 | impl ToChalk for ProjectionPredicate { | ||
444 | type Chalk = chalk_ir::AliasEq<Interner>; | ||
445 | |||
446 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { | ||
447 | chalk_ir::AliasEq { | ||
448 | alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)), | ||
449 | ty: self.ty.to_chalk(db), | ||
450 | } | ||
451 | } | ||
452 | |||
453 | fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { | ||
454 | unimplemented!() | ||
455 | } | ||
456 | } | ||
457 | |||
458 | impl ToChalk for Obligation { | ||
459 | type Chalk = chalk_ir::DomainGoal<Interner>; | ||
460 | |||
461 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { | ||
462 | match self { | ||
463 | Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), | ||
464 | Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner), | ||
465 | } | ||
466 | } | ||
467 | |||
468 | fn from_chalk(_db: &dyn HirDatabase, _goal: chalk_ir::DomainGoal<Interner>) -> Self { | ||
469 | unimplemented!() | ||
470 | } | ||
471 | } | ||
472 | |||
473 | impl<T> ToChalk for Canonical<T> | ||
474 | where | ||
475 | T: ToChalk, | ||
476 | T::Chalk: HasInterner<Interner = Interner>, | ||
477 | { | ||
478 | type Chalk = chalk_ir::Canonical<T::Chalk>; | ||
479 | |||
480 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | ||
481 | let parameter = chalk_ir::CanonicalVarKind::new( | ||
482 | chalk_ir::VariableKind::Ty, | ||
483 | chalk_ir::UniverseIndex::ROOT, | ||
484 | ); | ||
485 | let value = self.value.to_chalk(db); | ||
486 | chalk_ir::Canonical { | ||
487 | value, | ||
488 | binders: chalk_ir::CanonicalVarKinds::from(&Interner, vec![parameter; self.num_vars]), | ||
489 | } | ||
490 | } | ||
491 | |||
492 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | ||
493 | Canonical { | ||
494 | num_vars: canonical.binders.len(&Interner), | ||
495 | value: from_chalk(db, canonical.value), | ||
496 | } | ||
497 | } | ||
498 | } | ||
499 | |||
500 | impl ToChalk for Arc<TraitEnvironment> { | ||
501 | type Chalk = chalk_ir::Environment<Interner>; | ||
502 | |||
503 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Environment<Interner> { | ||
504 | let mut clauses = Vec::new(); | ||
505 | for pred in &self.predicates { | ||
506 | if pred.is_error() { | ||
507 | // for env, we just ignore errors | ||
508 | continue; | ||
509 | } | ||
510 | let program_clause: chalk_ir::ProgramClause<Interner> = | ||
511 | pred.clone().to_chalk(db).cast(&Interner); | ||
512 | clauses.push(program_clause.into_from_env_clause(&Interner)); | ||
513 | } | ||
514 | chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses) | ||
515 | } | ||
516 | |||
517 | fn from_chalk( | ||
518 | _db: &dyn HirDatabase, | ||
519 | _env: chalk_ir::Environment<Interner>, | ||
520 | ) -> Arc<TraitEnvironment> { | ||
521 | unimplemented!() | ||
522 | } | ||
523 | } | ||
524 | |||
525 | impl<T: ToChalk> ToChalk for InEnvironment<T> | ||
526 | where | ||
527 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
528 | { | ||
529 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | ||
530 | |||
531 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | ||
532 | chalk_ir::InEnvironment { | ||
533 | environment: self.environment.to_chalk(db), | ||
534 | goal: self.value.to_chalk(db), | ||
535 | } | ||
536 | } | ||
537 | |||
538 | fn from_chalk( | ||
539 | db: &dyn HirDatabase, | ||
540 | in_env: chalk_ir::InEnvironment<T::Chalk>, | ||
541 | ) -> InEnvironment<T> { | ||
542 | InEnvironment { | ||
543 | environment: from_chalk(db, in_env.environment), | ||
544 | value: from_chalk(db, in_env.goal), | ||
545 | } | ||
546 | } | ||
547 | } | ||
548 | |||
549 | impl ToChalk for builtin::BuiltinImplData { | ||
550 | type Chalk = ImplDatum; | ||
551 | |||
552 | fn to_chalk(self, db: &dyn HirDatabase) -> ImplDatum { | ||
553 | let impl_type = chalk_rust_ir::ImplType::External; | ||
554 | let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); | ||
555 | |||
556 | let impl_datum_bound = | ||
557 | chalk_rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses }; | ||
558 | let associated_ty_value_ids = | ||
559 | self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect(); | ||
560 | chalk_rust_ir::ImplDatum { | ||
561 | binders: make_binders(impl_datum_bound, self.num_vars), | ||
562 | impl_type, | ||
563 | polarity: chalk_rust_ir::Polarity::Positive, | ||
564 | associated_ty_value_ids, | ||
565 | } | ||
566 | } | ||
567 | |||
568 | fn from_chalk(_db: &dyn HirDatabase, _data: ImplDatum) -> Self { | ||
569 | unimplemented!() | ||
570 | } | ||
571 | } | ||
572 | |||
573 | impl ToChalk for builtin::BuiltinImplAssocTyValueData { | ||
574 | type Chalk = AssociatedTyValue; | ||
575 | |||
576 | fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue { | ||
577 | let ty = self.value.to_chalk(db); | ||
578 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty }; | ||
579 | |||
580 | chalk_rust_ir::AssociatedTyValue { | ||
581 | associated_ty_id: self.assoc_ty_id.to_chalk(db), | ||
582 | impl_id: self.impl_.to_chalk(db), | ||
583 | value: make_binders(value_bound, self.num_vars), | ||
584 | } | ||
585 | } | ||
586 | |||
587 | fn from_chalk( | ||
588 | _db: &dyn HirDatabase, | ||
589 | _data: AssociatedTyValue, | ||
590 | ) -> builtin::BuiltinImplAssocTyValueData { | ||
591 | unimplemented!() | ||
592 | } | ||
593 | } | ||
594 | |||
595 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | ||
596 | where | ||
597 | T: HasInterner<Interner = Interner>, | ||
598 | { | ||
599 | chalk_ir::Binders::new( | ||
600 | chalk_ir::VariableKinds::from( | ||
601 | &Interner, | ||
602 | std::iter::repeat(chalk_ir::VariableKind::Ty).take(num_vars), | ||
603 | ), | ||
604 | value, | ||
605 | ) | ||
606 | } | ||
607 | |||
608 | pub(super) fn convert_where_clauses( | ||
609 | db: &dyn HirDatabase, | ||
610 | def: GenericDefId, | ||
611 | substs: &Substs, | ||
612 | ) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> { | ||
613 | let generic_predicates = db.generic_predicates(def); | ||
614 | let mut result = Vec::with_capacity(generic_predicates.len()); | ||
615 | for pred in generic_predicates.iter() { | ||
616 | if pred.value.is_error() { | ||
617 | // skip errored predicates completely | ||
618 | continue; | ||
619 | } | ||
620 | result.push(pred.clone().subst(substs).to_chalk(db)); | ||
621 | } | ||
622 | result | ||
623 | } | ||
624 | |||
625 | pub(super) fn generic_predicate_to_inline_bound( | ||
626 | db: &dyn HirDatabase, | ||
627 | pred: &GenericPredicate, | ||
628 | self_ty: &Ty, | ||
629 | ) -> Option<chalk_rust_ir::InlineBound<Interner>> { | ||
630 | // An InlineBound is like a GenericPredicate, except the self type is left out. | ||
631 | // We don't have a special type for this, but Chalk does. | ||
632 | match pred { | ||
633 | GenericPredicate::Implemented(trait_ref) => { | ||
634 | if &trait_ref.substs[0] != self_ty { | ||
635 | // we can only convert predicates back to type bounds if they | ||
636 | // have the expected self type | ||
637 | return None; | ||
638 | } | ||
639 | let args_no_self = trait_ref.substs[1..] | ||
640 | .iter() | ||
641 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | ||
642 | .collect(); | ||
643 | let trait_bound = | ||
644 | chalk_rust_ir::TraitBound { trait_id: trait_ref.trait_.to_chalk(db), args_no_self }; | ||
645 | Some(chalk_rust_ir::InlineBound::TraitBound(trait_bound)) | ||
646 | } | ||
647 | GenericPredicate::Projection(proj) => { | ||
648 | if &proj.projection_ty.parameters[0] != self_ty { | ||
649 | return None; | ||
650 | } | ||
651 | let trait_ = match proj.projection_ty.associated_ty.lookup(db.upcast()).container { | ||
652 | AssocContainerId::TraitId(t) => t, | ||
653 | _ => panic!("associated type not in trait"), | ||
654 | }; | ||
655 | let args_no_self = proj.projection_ty.parameters[1..] | ||
656 | .iter() | ||
657 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | ||
658 | .collect(); | ||
659 | let alias_eq_bound = chalk_rust_ir::AliasEqBound { | ||
660 | value: proj.ty.clone().to_chalk(db), | ||
661 | trait_bound: chalk_rust_ir::TraitBound { | ||
662 | trait_id: trait_.to_chalk(db), | ||
663 | args_no_self, | ||
664 | }, | ||
665 | associated_ty_id: proj.projection_ty.associated_ty.to_chalk(db), | ||
666 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | ||
667 | }; | ||
668 | Some(chalk_rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | ||
669 | } | ||
670 | GenericPredicate::Error => None, | ||
671 | } | ||
672 | } | ||