diff options
Diffstat (limited to 'crates/ra_hir/src/ty/traits/chalk.rs')
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 884 |
1 files changed, 0 insertions, 884 deletions
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs deleted file mode 100644 index 1a93e5e50..000000000 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ /dev/null | |||
@@ -1,884 +0,0 @@ | |||
1 | //! Conversion code from/to Chalk. | ||
2 | use std::sync::Arc; | ||
3 | |||
4 | use log::debug; | ||
5 | |||
6 | use chalk_ir::{ | ||
7 | cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, | ||
8 | TypeKindId, TypeName, UniverseIndex, | ||
9 | }; | ||
10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; | ||
11 | |||
12 | use hir_def::lang_item::LangItemTarget; | ||
13 | use hir_expand::name; | ||
14 | |||
15 | use ra_db::salsa::{InternId, InternKey}; | ||
16 | |||
17 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | ||
18 | use crate::{ | ||
19 | db::HirDatabase, | ||
20 | ty::display::HirDisplay, | ||
21 | ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, | ||
22 | Crate, GenericDef, ImplBlock, Trait, TypeAlias, | ||
23 | }; | ||
24 | |||
25 | /// This represents a trait whose name we could not resolve. | ||
26 | const UNKNOWN_TRAIT: chalk_ir::TraitId = | ||
27 | chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); | ||
28 | |||
29 | pub(super) trait ToChalk { | ||
30 | type Chalk; | ||
31 | fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; | ||
32 | fn from_chalk(db: &impl HirDatabase, chalk: Self::Chalk) -> Self; | ||
33 | } | ||
34 | |||
35 | pub(super) fn from_chalk<T, ChalkT>(db: &impl HirDatabase, chalk: ChalkT) -> T | ||
36 | where | ||
37 | T: ToChalk<Chalk = ChalkT>, | ||
38 | { | ||
39 | T::from_chalk(db, chalk) | ||
40 | } | ||
41 | |||
42 | impl ToChalk for Ty { | ||
43 | type Chalk = chalk_ir::Ty<ChalkIr>; | ||
44 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<ChalkIr> { | ||
45 | match self { | ||
46 | Ty::Apply(apply_ty) => { | ||
47 | let name = match apply_ty.ctor { | ||
48 | TypeCtor::AssociatedType(type_alias) => { | ||
49 | let type_id = type_alias.to_chalk(db); | ||
50 | TypeName::AssociatedType(type_id) | ||
51 | } | ||
52 | _ => { | ||
53 | // other TypeCtors get interned and turned into a chalk StructId | ||
54 | let struct_id = apply_ty.ctor.to_chalk(db); | ||
55 | TypeName::TypeKindId(struct_id.into()) | ||
56 | } | ||
57 | }; | ||
58 | let parameters = apply_ty.parameters.to_chalk(db); | ||
59 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() | ||
60 | } | ||
61 | Ty::Projection(proj_ty) => { | ||
62 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | ||
63 | let parameters = proj_ty.parameters.to_chalk(db); | ||
64 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() | ||
65 | } | ||
66 | Ty::Param { idx, .. } => { | ||
67 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() | ||
68 | } | ||
69 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), | ||
70 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | ||
71 | Ty::Dyn(predicates) => { | ||
72 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); | ||
73 | chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() | ||
74 | } | ||
75 | Ty::Opaque(predicates) => { | ||
76 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); | ||
77 | chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() | ||
78 | } | ||
79 | Ty::Unknown => { | ||
80 | let parameters = Vec::new(); | ||
81 | let name = TypeName::Error; | ||
82 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { | ||
87 | match chalk.data().clone() { | ||
88 | chalk_ir::TyData::Apply(apply_ty) => { | ||
89 | // FIXME this is kind of hacky due to the fact that | ||
90 | // TypeName::Placeholder is a Ty::Param on our side | ||
91 | match apply_ty.name { | ||
92 | TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { | ||
93 | let ctor = from_chalk(db, struct_id); | ||
94 | let parameters = from_chalk(db, apply_ty.parameters); | ||
95 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
96 | } | ||
97 | TypeName::AssociatedType(type_id) => { | ||
98 | let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id)); | ||
99 | let parameters = from_chalk(db, apply_ty.parameters); | ||
100 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
101 | } | ||
102 | TypeName::Error => Ty::Unknown, | ||
103 | // FIXME handle TypeKindId::Trait/Type here | ||
104 | TypeName::TypeKindId(_) => unimplemented!(), | ||
105 | TypeName::Placeholder(idx) => { | ||
106 | assert_eq!(idx.ui, UniverseIndex::ROOT); | ||
107 | Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | chalk_ir::TyData::Projection(proj) => { | ||
112 | let associated_ty = from_chalk(db, proj.associated_ty_id); | ||
113 | let parameters = from_chalk(db, proj.parameters); | ||
114 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | ||
115 | } | ||
116 | chalk_ir::TyData::ForAll(_) => unimplemented!(), | ||
117 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), | ||
118 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, | ||
119 | chalk_ir::TyData::Dyn(where_clauses) => { | ||
120 | assert_eq!(where_clauses.binders.len(), 1); | ||
121 | let predicates = | ||
122 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | ||
123 | Ty::Dyn(predicates) | ||
124 | } | ||
125 | chalk_ir::TyData::Opaque(where_clauses) => { | ||
126 | assert_eq!(where_clauses.binders.len(), 1); | ||
127 | let predicates = | ||
128 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | ||
129 | Ty::Opaque(predicates) | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | |||
135 | impl ToChalk for Substs { | ||
136 | type Chalk = Vec<chalk_ir::Parameter<ChalkIr>>; | ||
137 | |||
138 | fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<ChalkIr>> { | ||
139 | self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() | ||
140 | } | ||
141 | |||
142 | fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter<ChalkIr>>) -> Substs { | ||
143 | let tys = parameters | ||
144 | .into_iter() | ||
145 | .map(|p| match p { | ||
146 | chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), | ||
147 | chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), | ||
148 | }) | ||
149 | .collect(); | ||
150 | Substs(tys) | ||
151 | } | ||
152 | } | ||
153 | |||
154 | impl ToChalk for TraitRef { | ||
155 | type Chalk = chalk_ir::TraitRef<ChalkIr>; | ||
156 | |||
157 | fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<ChalkIr> { | ||
158 | let trait_id = self.trait_.to_chalk(db); | ||
159 | let parameters = self.substs.to_chalk(db); | ||
160 | chalk_ir::TraitRef { trait_id, parameters } | ||
161 | } | ||
162 | |||
163 | fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<ChalkIr>) -> Self { | ||
164 | let trait_ = from_chalk(db, trait_ref.trait_id); | ||
165 | let substs = from_chalk(db, trait_ref.parameters); | ||
166 | TraitRef { trait_, substs } | ||
167 | } | ||
168 | } | ||
169 | |||
170 | impl ToChalk for Trait { | ||
171 | type Chalk = chalk_ir::TraitId; | ||
172 | |||
173 | fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { | ||
174 | chalk_ir::TraitId(id_to_chalk(self.id)) | ||
175 | } | ||
176 | |||
177 | fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> Trait { | ||
178 | Trait { id: id_from_chalk(trait_id.0) } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | impl ToChalk for TypeCtor { | ||
183 | type Chalk = chalk_ir::StructId; | ||
184 | |||
185 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::StructId { | ||
186 | db.intern_type_ctor(self).into() | ||
187 | } | ||
188 | |||
189 | fn from_chalk(db: &impl HirDatabase, struct_id: chalk_ir::StructId) -> TypeCtor { | ||
190 | db.lookup_intern_type_ctor(struct_id.into()) | ||
191 | } | ||
192 | } | ||
193 | |||
194 | impl ToChalk for Impl { | ||
195 | type Chalk = chalk_ir::ImplId; | ||
196 | |||
197 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { | ||
198 | db.intern_chalk_impl(self).into() | ||
199 | } | ||
200 | |||
201 | fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { | ||
202 | db.lookup_intern_chalk_impl(impl_id.into()) | ||
203 | } | ||
204 | } | ||
205 | |||
206 | impl ToChalk for TypeAlias { | ||
207 | type Chalk = chalk_ir::TypeId; | ||
208 | |||
209 | fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { | ||
210 | chalk_ir::TypeId(id_to_chalk(self.id)) | ||
211 | } | ||
212 | |||
213 | fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAlias { | ||
214 | TypeAlias { id: id_from_chalk(type_alias_id.0) } | ||
215 | } | ||
216 | } | ||
217 | |||
218 | impl ToChalk for AssocTyValue { | ||
219 | type Chalk = chalk_rust_ir::AssociatedTyValueId; | ||
220 | |||
221 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { | ||
222 | db.intern_assoc_ty_value(self).into() | ||
223 | } | ||
224 | |||
225 | fn from_chalk( | ||
226 | db: &impl HirDatabase, | ||
227 | assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId, | ||
228 | ) -> AssocTyValue { | ||
229 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
230 | } | ||
231 | } | ||
232 | |||
233 | impl ToChalk for GenericPredicate { | ||
234 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; | ||
235 | |||
236 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<ChalkIr> { | ||
237 | match self { | ||
238 | GenericPredicate::Implemented(trait_ref) => { | ||
239 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) | ||
240 | } | ||
241 | GenericPredicate::Projection(projection_pred) => make_binders( | ||
242 | chalk_ir::WhereClause::ProjectionEq(chalk_ir::ProjectionEq { | ||
243 | projection: projection_pred.projection_ty.to_chalk(db), | ||
244 | ty: projection_pred.ty.to_chalk(db), | ||
245 | }), | ||
246 | 0, | ||
247 | ), | ||
248 | GenericPredicate::Error => { | ||
249 | let impossible_trait_ref = chalk_ir::TraitRef { | ||
250 | trait_id: UNKNOWN_TRAIT, | ||
251 | parameters: vec![Ty::Unknown.to_chalk(db).cast()], | ||
252 | }; | ||
253 | make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0) | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | |||
258 | fn from_chalk( | ||
259 | db: &impl HirDatabase, | ||
260 | where_clause: chalk_ir::QuantifiedWhereClause<ChalkIr>, | ||
261 | ) -> GenericPredicate { | ||
262 | match where_clause.value { | ||
263 | chalk_ir::WhereClause::Implemented(tr) => { | ||
264 | if tr.trait_id == UNKNOWN_TRAIT { | ||
265 | // FIXME we need an Error enum on the Chalk side to avoid this | ||
266 | return GenericPredicate::Error; | ||
267 | } | ||
268 | GenericPredicate::Implemented(from_chalk(db, tr)) | ||
269 | } | ||
270 | chalk_ir::WhereClause::ProjectionEq(projection_eq) => { | ||
271 | let projection_ty = from_chalk(db, projection_eq.projection); | ||
272 | let ty = from_chalk(db, projection_eq.ty); | ||
273 | GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | |||
279 | impl ToChalk for ProjectionTy { | ||
280 | type Chalk = chalk_ir::ProjectionTy<ChalkIr>; | ||
281 | |||
282 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<ChalkIr> { | ||
283 | chalk_ir::ProjectionTy { | ||
284 | associated_ty_id: self.associated_ty.to_chalk(db), | ||
285 | parameters: self.parameters.to_chalk(db), | ||
286 | } | ||
287 | } | ||
288 | |||
289 | fn from_chalk( | ||
290 | db: &impl HirDatabase, | ||
291 | projection_ty: chalk_ir::ProjectionTy<ChalkIr>, | ||
292 | ) -> ProjectionTy { | ||
293 | ProjectionTy { | ||
294 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | ||
295 | parameters: from_chalk(db, projection_ty.parameters), | ||
296 | } | ||
297 | } | ||
298 | } | ||
299 | |||
300 | impl ToChalk for super::ProjectionPredicate { | ||
301 | type Chalk = chalk_ir::Normalize<ChalkIr>; | ||
302 | |||
303 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<ChalkIr> { | ||
304 | chalk_ir::Normalize { | ||
305 | projection: self.projection_ty.to_chalk(db), | ||
306 | ty: self.ty.to_chalk(db), | ||
307 | } | ||
308 | } | ||
309 | |||
310 | fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<ChalkIr>) -> Self { | ||
311 | unimplemented!() | ||
312 | } | ||
313 | } | ||
314 | |||
315 | impl ToChalk for Obligation { | ||
316 | type Chalk = chalk_ir::DomainGoal<ChalkIr>; | ||
317 | |||
318 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<ChalkIr> { | ||
319 | match self { | ||
320 | Obligation::Trait(tr) => tr.to_chalk(db).cast(), | ||
321 | Obligation::Projection(pr) => pr.to_chalk(db).cast(), | ||
322 | } | ||
323 | } | ||
324 | |||
325 | fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<ChalkIr>) -> Self { | ||
326 | unimplemented!() | ||
327 | } | ||
328 | } | ||
329 | |||
330 | impl<T> ToChalk for Canonical<T> | ||
331 | where | ||
332 | T: ToChalk, | ||
333 | { | ||
334 | type Chalk = chalk_ir::Canonical<T::Chalk>; | ||
335 | |||
336 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | ||
337 | let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT); | ||
338 | let value = self.value.to_chalk(db); | ||
339 | let canonical = chalk_ir::Canonical { value, binders: vec![parameter; self.num_vars] }; | ||
340 | canonical | ||
341 | } | ||
342 | |||
343 | fn from_chalk(db: &impl HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | ||
344 | Canonical { num_vars: canonical.binders.len(), value: from_chalk(db, canonical.value) } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | impl ToChalk for Arc<super::TraitEnvironment> { | ||
349 | type Chalk = chalk_ir::Environment<ChalkIr>; | ||
350 | |||
351 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment<ChalkIr> { | ||
352 | let mut clauses = Vec::new(); | ||
353 | for pred in &self.predicates { | ||
354 | if pred.is_error() { | ||
355 | // for env, we just ignore errors | ||
356 | continue; | ||
357 | } | ||
358 | let program_clause: chalk_ir::ProgramClause<ChalkIr> = pred.clone().to_chalk(db).cast(); | ||
359 | clauses.push(program_clause.into_from_env_clause()); | ||
360 | } | ||
361 | chalk_ir::Environment::new().add_clauses(clauses) | ||
362 | } | ||
363 | |||
364 | fn from_chalk( | ||
365 | _db: &impl HirDatabase, | ||
366 | _env: chalk_ir::Environment<ChalkIr>, | ||
367 | ) -> Arc<super::TraitEnvironment> { | ||
368 | unimplemented!() | ||
369 | } | ||
370 | } | ||
371 | |||
372 | impl<T: ToChalk> ToChalk for super::InEnvironment<T> | ||
373 | where | ||
374 | T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = ChalkIr>, | ||
375 | { | ||
376 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | ||
377 | |||
378 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | ||
379 | chalk_ir::InEnvironment { | ||
380 | environment: self.environment.to_chalk(db), | ||
381 | goal: self.value.to_chalk(db), | ||
382 | } | ||
383 | } | ||
384 | |||
385 | fn from_chalk( | ||
386 | db: &impl HirDatabase, | ||
387 | in_env: chalk_ir::InEnvironment<T::Chalk>, | ||
388 | ) -> super::InEnvironment<T> { | ||
389 | super::InEnvironment { | ||
390 | environment: from_chalk(db, in_env.environment), | ||
391 | value: from_chalk(db, in_env.goal), | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | |||
396 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | ||
397 | chalk_ir::Binders { | ||
398 | value, | ||
399 | binders: std::iter::repeat(chalk_ir::ParameterKind::Ty(())).take(num_vars).collect(), | ||
400 | } | ||
401 | } | ||
402 | |||
403 | fn convert_where_clauses( | ||
404 | db: &impl HirDatabase, | ||
405 | def: GenericDef, | ||
406 | substs: &Substs, | ||
407 | ) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> { | ||
408 | let generic_predicates = db.generic_predicates(def); | ||
409 | let mut result = Vec::with_capacity(generic_predicates.len()); | ||
410 | for pred in generic_predicates.iter() { | ||
411 | if pred.is_error() { | ||
412 | // HACK: Return just the single predicate (which is always false | ||
413 | // anyway), otherwise Chalk can easily get into slow situations | ||
414 | return vec![pred.clone().subst(substs).to_chalk(db)]; | ||
415 | } | ||
416 | result.push(pred.clone().subst(substs).to_chalk(db)); | ||
417 | } | ||
418 | result | ||
419 | } | ||
420 | |||
421 | impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB> | ||
422 | where | ||
423 | DB: HirDatabase, | ||
424 | { | ||
425 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum<ChalkIr>> { | ||
426 | self.db.associated_ty_data(id) | ||
427 | } | ||
428 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum<ChalkIr>> { | ||
429 | self.db.trait_datum(self.krate, trait_id) | ||
430 | } | ||
431 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> { | ||
432 | self.db.struct_datum(self.krate, struct_id) | ||
433 | } | ||
434 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum<ChalkIr>> { | ||
435 | self.db.impl_datum(self.krate, impl_id) | ||
436 | } | ||
437 | fn impls_for_trait( | ||
438 | &self, | ||
439 | trait_id: chalk_ir::TraitId, | ||
440 | parameters: &[Parameter<ChalkIr>], | ||
441 | ) -> Vec<ImplId> { | ||
442 | debug!("impls_for_trait {:?}", trait_id); | ||
443 | if trait_id == UNKNOWN_TRAIT { | ||
444 | return Vec::new(); | ||
445 | } | ||
446 | let trait_: Trait = from_chalk(self.db, trait_id); | ||
447 | let mut result: Vec<_> = self | ||
448 | .db | ||
449 | .impls_for_trait(self.krate, trait_) | ||
450 | .iter() | ||
451 | .copied() | ||
452 | .map(Impl::ImplBlock) | ||
453 | .map(|impl_| impl_.to_chalk(self.db)) | ||
454 | .collect(); | ||
455 | |||
456 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); | ||
457 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { | ||
458 | for &fn_trait in | ||
459 | [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() | ||
460 | { | ||
461 | if let Some(actual_trait) = get_fn_trait(self.db, self.krate, fn_trait) { | ||
462 | if trait_ == actual_trait { | ||
463 | let impl_ = super::ClosureFnTraitImplData { def, expr, fn_trait }; | ||
464 | result.push(Impl::ClosureFnTraitImpl(impl_).to_chalk(self.db)); | ||
465 | } | ||
466 | } | ||
467 | } | ||
468 | } | ||
469 | |||
470 | debug!("impls_for_trait returned {} impls", result.len()); | ||
471 | result | ||
472 | } | ||
473 | fn impl_provided_for( | ||
474 | &self, | ||
475 | auto_trait_id: chalk_ir::TraitId, | ||
476 | struct_id: chalk_ir::StructId, | ||
477 | ) -> bool { | ||
478 | debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); | ||
479 | false // FIXME | ||
480 | } | ||
481 | fn type_name(&self, _id: TypeKindId) -> Identifier { | ||
482 | unimplemented!() | ||
483 | } | ||
484 | fn associated_ty_value( | ||
485 | &self, | ||
486 | id: chalk_rust_ir::AssociatedTyValueId, | ||
487 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
488 | self.db.associated_ty_value(self.krate, id) | ||
489 | } | ||
490 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { | ||
491 | vec![] | ||
492 | } | ||
493 | fn local_impls_to_coherence_check( | ||
494 | &self, | ||
495 | _trait_id: chalk_ir::TraitId, | ||
496 | ) -> Vec<chalk_ir::ImplId> { | ||
497 | // We don't do coherence checking (yet) | ||
498 | unimplemented!() | ||
499 | } | ||
500 | } | ||
501 | |||
502 | pub(crate) fn associated_ty_data_query( | ||
503 | db: &impl HirDatabase, | ||
504 | id: TypeId, | ||
505 | ) -> Arc<AssociatedTyDatum<ChalkIr>> { | ||
506 | debug!("associated_ty_data {:?}", id); | ||
507 | let type_alias: TypeAlias = from_chalk(db, id); | ||
508 | let trait_ = match type_alias.container(db) { | ||
509 | Some(crate::Container::Trait(t)) => t, | ||
510 | _ => panic!("associated type not in trait"), | ||
511 | }; | ||
512 | let generic_params = db.generic_params(type_alias.id.into()); | ||
513 | let bound_data = chalk_rust_ir::AssociatedTyDatumBound { | ||
514 | // FIXME add bounds and where clauses | ||
515 | bounds: vec![], | ||
516 | where_clauses: vec![], | ||
517 | }; | ||
518 | let datum = AssociatedTyDatum { | ||
519 | trait_id: trait_.to_chalk(db), | ||
520 | id, | ||
521 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), | ||
522 | binders: make_binders(bound_data, generic_params.count_params_including_parent()), | ||
523 | }; | ||
524 | Arc::new(datum) | ||
525 | } | ||
526 | |||
527 | pub(crate) fn trait_datum_query( | ||
528 | db: &impl HirDatabase, | ||
529 | krate: Crate, | ||
530 | trait_id: chalk_ir::TraitId, | ||
531 | ) -> Arc<TraitDatum<ChalkIr>> { | ||
532 | debug!("trait_datum {:?}", trait_id); | ||
533 | if trait_id == UNKNOWN_TRAIT { | ||
534 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; | ||
535 | |||
536 | let flags = chalk_rust_ir::TraitFlags { | ||
537 | auto: false, | ||
538 | marker: false, | ||
539 | upstream: true, | ||
540 | fundamental: false, | ||
541 | non_enumerable: true, | ||
542 | coinductive: false, | ||
543 | }; | ||
544 | return Arc::new(TraitDatum { | ||
545 | id: trait_id, | ||
546 | binders: make_binders(trait_datum_bound, 1), | ||
547 | flags, | ||
548 | associated_ty_ids: vec![], | ||
549 | }); | ||
550 | } | ||
551 | let trait_: Trait = from_chalk(db, trait_id); | ||
552 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); | ||
553 | let generic_params = db.generic_params(trait_.id.into()); | ||
554 | let bound_vars = Substs::bound_vars(&generic_params); | ||
555 | let flags = chalk_rust_ir::TraitFlags { | ||
556 | auto: trait_.is_auto(db), | ||
557 | upstream: trait_.module(db).krate() != krate, | ||
558 | non_enumerable: true, | ||
559 | coinductive: false, // only relevant for Chalk testing | ||
560 | // FIXME set these flags correctly | ||
561 | marker: false, | ||
562 | fundamental: false, | ||
563 | }; | ||
564 | let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); | ||
565 | let associated_ty_ids = trait_ | ||
566 | .items(db) | ||
567 | .into_iter() | ||
568 | .filter_map(|trait_item| match trait_item { | ||
569 | crate::AssocItem::TypeAlias(type_alias) => Some(type_alias), | ||
570 | _ => None, | ||
571 | }) | ||
572 | .map(|type_alias| type_alias.to_chalk(db)) | ||
573 | .collect(); | ||
574 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; | ||
575 | let trait_datum = TraitDatum { | ||
576 | id: trait_id, | ||
577 | binders: make_binders(trait_datum_bound, bound_vars.len()), | ||
578 | flags, | ||
579 | associated_ty_ids, | ||
580 | }; | ||
581 | Arc::new(trait_datum) | ||
582 | } | ||
583 | |||
584 | pub(crate) fn struct_datum_query( | ||
585 | db: &impl HirDatabase, | ||
586 | krate: Crate, | ||
587 | struct_id: chalk_ir::StructId, | ||
588 | ) -> Arc<StructDatum<ChalkIr>> { | ||
589 | debug!("struct_datum {:?}", struct_id); | ||
590 | let type_ctor: TypeCtor = from_chalk(db, struct_id); | ||
591 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | ||
592 | let num_params = type_ctor.num_ty_params(db); | ||
593 | let upstream = type_ctor.krate(db) != Some(krate); | ||
594 | let where_clauses = type_ctor | ||
595 | .as_generic_def() | ||
596 | .map(|generic_def| { | ||
597 | let generic_params = db.generic_params(generic_def.into()); | ||
598 | let bound_vars = Substs::bound_vars(&generic_params); | ||
599 | convert_where_clauses(db, generic_def, &bound_vars) | ||
600 | }) | ||
601 | .unwrap_or_else(Vec::new); | ||
602 | let flags = chalk_rust_ir::StructFlags { | ||
603 | upstream, | ||
604 | // FIXME set fundamental flag correctly | ||
605 | fundamental: false, | ||
606 | }; | ||
607 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { | ||
608 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | ||
609 | where_clauses, | ||
610 | }; | ||
611 | let struct_datum = | ||
612 | StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags }; | ||
613 | Arc::new(struct_datum) | ||
614 | } | ||
615 | |||
616 | pub(crate) fn impl_datum_query( | ||
617 | db: &impl HirDatabase, | ||
618 | krate: Crate, | ||
619 | impl_id: ImplId, | ||
620 | ) -> Arc<ImplDatum<ChalkIr>> { | ||
621 | let _p = ra_prof::profile("impl_datum"); | ||
622 | debug!("impl_datum {:?}", impl_id); | ||
623 | let impl_: Impl = from_chalk(db, impl_id); | ||
624 | match impl_ { | ||
625 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), | ||
626 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), | ||
627 | } | ||
628 | .unwrap_or_else(invalid_impl_datum) | ||
629 | } | ||
630 | |||
631 | fn impl_block_datum( | ||
632 | db: &impl HirDatabase, | ||
633 | krate: Crate, | ||
634 | impl_id: ImplId, | ||
635 | impl_block: ImplBlock, | ||
636 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { | ||
637 | let generic_params = db.generic_params(impl_block.id.into()); | ||
638 | let bound_vars = Substs::bound_vars(&generic_params); | ||
639 | let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); | ||
640 | let trait_ = trait_ref.trait_; | ||
641 | let impl_type = if impl_block.krate(db) == krate { | ||
642 | chalk_rust_ir::ImplType::Local | ||
643 | } else { | ||
644 | chalk_rust_ir::ImplType::External | ||
645 | }; | ||
646 | let where_clauses = convert_where_clauses(db, impl_block.into(), &bound_vars); | ||
647 | let negative = impl_block.is_negative(db); | ||
648 | debug!( | ||
649 | "impl {:?}: {}{} where {:?}", | ||
650 | impl_id, | ||
651 | if negative { "!" } else { "" }, | ||
652 | trait_ref.display(db), | ||
653 | where_clauses | ||
654 | ); | ||
655 | let trait_ref = trait_ref.to_chalk(db); | ||
656 | |||
657 | let polarity = if negative { | ||
658 | chalk_rust_ir::Polarity::Negative | ||
659 | } else { | ||
660 | chalk_rust_ir::Polarity::Positive | ||
661 | }; | ||
662 | |||
663 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; | ||
664 | let associated_ty_value_ids = impl_block | ||
665 | .items(db) | ||
666 | .into_iter() | ||
667 | .filter_map(|item| match item { | ||
668 | crate::AssocItem::TypeAlias(type_alias) => Some(type_alias), | ||
669 | _ => None, | ||
670 | }) | ||
671 | .filter(|type_alias| { | ||
672 | // don't include associated types that don't exist in the trait | ||
673 | trait_.associated_type_by_name(db, &type_alias.name(db)).is_some() | ||
674 | }) | ||
675 | .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) | ||
676 | .collect(); | ||
677 | debug!("impl_datum: {:?}", impl_datum_bound); | ||
678 | let impl_datum = ImplDatum { | ||
679 | binders: make_binders(impl_datum_bound, bound_vars.len()), | ||
680 | impl_type, | ||
681 | polarity, | ||
682 | associated_ty_value_ids, | ||
683 | }; | ||
684 | Some(Arc::new(impl_datum)) | ||
685 | } | ||
686 | |||
687 | fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> { | ||
688 | let trait_ref = chalk_ir::TraitRef { | ||
689 | trait_id: UNKNOWN_TRAIT, | ||
690 | parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], | ||
691 | }; | ||
692 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; | ||
693 | let impl_datum = ImplDatum { | ||
694 | binders: make_binders(impl_datum_bound, 1), | ||
695 | impl_type: chalk_rust_ir::ImplType::External, | ||
696 | polarity: chalk_rust_ir::Polarity::Positive, | ||
697 | associated_ty_value_ids: Vec::new(), | ||
698 | }; | ||
699 | Arc::new(impl_datum) | ||
700 | } | ||
701 | |||
702 | fn closure_fn_trait_impl_datum( | ||
703 | db: &impl HirDatabase, | ||
704 | krate: Crate, | ||
705 | data: super::ClosureFnTraitImplData, | ||
706 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { | ||
707 | // for some closure |X, Y| -> Z: | ||
708 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } | ||
709 | |||
710 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait | ||
711 | |||
712 | // validate FnOnce trait, since we need it in the assoc ty value definition | ||
713 | // and don't want to return a valid value only to find out later that FnOnce | ||
714 | // is broken | ||
715 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
716 | fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | ||
717 | |||
718 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { | ||
719 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | ||
720 | _ => { | ||
721 | log::warn!("closure for closure type {:?} not found", data); | ||
722 | 0 | ||
723 | } | ||
724 | }; | ||
725 | |||
726 | let arg_ty = Ty::apply( | ||
727 | TypeCtor::Tuple { cardinality: num_args }, | ||
728 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), | ||
729 | ); | ||
730 | let sig_ty = Ty::apply( | ||
731 | TypeCtor::FnPtr { num_args }, | ||
732 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), | ||
733 | ); | ||
734 | |||
735 | let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); | ||
736 | |||
737 | let trait_ref = TraitRef { | ||
738 | trait_, | ||
739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | ||
740 | }; | ||
741 | |||
742 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); | ||
743 | |||
744 | let impl_type = chalk_rust_ir::ImplType::External; | ||
745 | |||
746 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | ||
747 | trait_ref: trait_ref.to_chalk(db), | ||
748 | where_clauses: Vec::new(), | ||
749 | }; | ||
750 | let impl_datum = ImplDatum { | ||
751 | binders: make_binders(impl_datum_bound, num_args as usize + 1), | ||
752 | impl_type, | ||
753 | polarity: chalk_rust_ir::Polarity::Positive, | ||
754 | associated_ty_value_ids: vec![output_ty_id], | ||
755 | }; | ||
756 | Some(Arc::new(impl_datum)) | ||
757 | } | ||
758 | |||
759 | pub(crate) fn associated_ty_value_query( | ||
760 | db: &impl HirDatabase, | ||
761 | krate: Crate, | ||
762 | id: chalk_rust_ir::AssociatedTyValueId, | ||
763 | ) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> { | ||
764 | let data: AssocTyValue = from_chalk(db, id); | ||
765 | match data { | ||
766 | AssocTyValue::TypeAlias(type_alias) => { | ||
767 | type_alias_associated_ty_value(db, krate, type_alias) | ||
768 | } | ||
769 | AssocTyValue::ClosureFnTraitImplOutput(data) => { | ||
770 | closure_fn_trait_output_assoc_ty_value(db, krate, data) | ||
771 | } | ||
772 | } | ||
773 | } | ||
774 | |||
775 | fn type_alias_associated_ty_value( | ||
776 | db: &impl HirDatabase, | ||
777 | _krate: Crate, | ||
778 | type_alias: TypeAlias, | ||
779 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
780 | let impl_block = type_alias.impl_block(db).expect("assoc ty value should be in impl"); | ||
781 | let impl_id = Impl::ImplBlock(impl_block).to_chalk(db); | ||
782 | let trait_ = impl_block | ||
783 | .target_trait_ref(db) | ||
784 | .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved | ||
785 | .trait_; | ||
786 | let assoc_ty = trait_ | ||
787 | .associated_type_by_name(db, &type_alias.name(db)) | ||
788 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | ||
789 | let generic_params = db.generic_params(impl_block.id.into()); | ||
790 | let bound_vars = Substs::bound_vars(&generic_params); | ||
791 | let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); | ||
792 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; | ||
793 | let value = chalk_rust_ir::AssociatedTyValue { | ||
794 | impl_id, | ||
795 | associated_ty_id: assoc_ty.to_chalk(db), | ||
796 | value: make_binders(value_bound, bound_vars.len()), | ||
797 | }; | ||
798 | Arc::new(value) | ||
799 | } | ||
800 | |||
801 | fn closure_fn_trait_output_assoc_ty_value( | ||
802 | db: &impl HirDatabase, | ||
803 | krate: Crate, | ||
804 | data: super::ClosureFnTraitImplData, | ||
805 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
806 | let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); | ||
807 | |||
808 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { | ||
809 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | ||
810 | _ => { | ||
811 | log::warn!("closure for closure type {:?} not found", data); | ||
812 | 0 | ||
813 | } | ||
814 | }; | ||
815 | |||
816 | let output_ty = Ty::Bound(num_args.into()); | ||
817 | |||
818 | let fn_once_trait = | ||
819 | get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); | ||
820 | |||
821 | let output_ty_id = fn_once_trait | ||
822 | .associated_type_by_name(db, &name::OUTPUT_TYPE) | ||
823 | .expect("assoc ty value should not exist"); | ||
824 | |||
825 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; | ||
826 | |||
827 | let value = chalk_rust_ir::AssociatedTyValue { | ||
828 | associated_ty_id: output_ty_id.to_chalk(db), | ||
829 | impl_id, | ||
830 | value: make_binders(value_bound, num_args as usize + 1), | ||
831 | }; | ||
832 | Arc::new(value) | ||
833 | } | ||
834 | |||
835 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | ||
836 | let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?; | ||
837 | match target { | ||
838 | LangItemTarget::TraitId(t) => Some(t.into()), | ||
839 | _ => None, | ||
840 | } | ||
841 | } | ||
842 | |||
843 | fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T { | ||
844 | T::from_intern_id(InternId::from(chalk_id.index)) | ||
845 | } | ||
846 | fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId { | ||
847 | chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } | ||
848 | } | ||
849 | |||
850 | impl From<chalk_ir::StructId> for crate::ty::TypeCtorId { | ||
851 | fn from(struct_id: chalk_ir::StructId) -> Self { | ||
852 | id_from_chalk(struct_id.0) | ||
853 | } | ||
854 | } | ||
855 | |||
856 | impl From<crate::ty::TypeCtorId> for chalk_ir::StructId { | ||
857 | fn from(type_ctor_id: crate::ty::TypeCtorId) -> Self { | ||
858 | chalk_ir::StructId(id_to_chalk(type_ctor_id)) | ||
859 | } | ||
860 | } | ||
861 | |||
862 | impl From<chalk_ir::ImplId> for crate::ty::traits::GlobalImplId { | ||
863 | fn from(impl_id: chalk_ir::ImplId) -> Self { | ||
864 | id_from_chalk(impl_id.0) | ||
865 | } | ||
866 | } | ||
867 | |||
868 | impl From<crate::ty::traits::GlobalImplId> for chalk_ir::ImplId { | ||
869 | fn from(impl_id: crate::ty::traits::GlobalImplId) -> Self { | ||
870 | chalk_ir::ImplId(id_to_chalk(impl_id)) | ||
871 | } | ||
872 | } | ||
873 | |||
874 | impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ty::traits::AssocTyValueId { | ||
875 | fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { | ||
876 | id_from_chalk(id.0) | ||
877 | } | ||
878 | } | ||
879 | |||
880 | impl From<crate::ty::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { | ||
881 | fn from(assoc_ty_value_id: crate::ty::traits::AssocTyValueId) -> Self { | ||
882 | chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) | ||
883 | } | ||
884 | } | ||