aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/traits/chalk.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/traits/chalk.rs')
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs884
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.
2use std::sync::Arc;
3
4use log::debug;
5
6use chalk_ir::{
7 cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId,
8 TypeKindId, TypeName, UniverseIndex,
9};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11
12use hir_def::lang_item::LangItemTarget;
13use hir_expand::name;
14
15use ra_db::salsa::{InternId, InternKey};
16
17use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
18use 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.
26const UNKNOWN_TRAIT: chalk_ir::TraitId =
27 chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() });
28
29pub(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
35pub(super) fn from_chalk<T, ChalkT>(db: &impl HirDatabase, chalk: ChalkT) -> T
36where
37 T: ToChalk<Chalk = ChalkT>,
38{
39 T::from_chalk(db, chalk)
40}
41
42impl 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
135impl 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
154impl 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
170impl 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
182impl 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
194impl 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
206impl 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
218impl 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
233impl 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
279impl 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
300impl 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
315impl 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
330impl<T> ToChalk for Canonical<T>
331where
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
348impl 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
372impl<T: ToChalk> ToChalk for super::InEnvironment<T>
373where
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
396fn 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
403fn 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
421impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB>
422where
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
502pub(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
527pub(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
584pub(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
616pub(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
631fn 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
687fn 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
702fn 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
759pub(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
775fn 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
801fn 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
835fn 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
843fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T {
844 T::from_intern_id(InternId::from(chalk_id.index))
845}
846fn 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
850impl 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
856impl 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
862impl 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
868impl 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
874impl 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
880impl 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}