]> git.lizzy.rs Git - rust.git/blob - crates/ra_hir/src/ty/traits/chalk.rs
Merge #1683
[rust.git] / crates / ra_hir / src / ty / traits / chalk.rs
1 //! Conversion code from/to Chalk.
2 use std::sync::Arc;
3
4 use log::debug;
5
6 use chalk_ir::{
7     cast::Cast, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, TypeKindId, TypeName,
8     UniverseIndex,
9 };
10 use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
11
12 use ra_db::salsa::{InternId, InternKey};
13 use test_utils::tested_by;
14
15 use super::{Canonical, ChalkContext, Obligation};
16 use crate::{
17     db::HirDatabase,
18     generics::GenericDef,
19     ty::display::HirDisplay,
20     ty::{
21         ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
22     },
23     Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias,
24 };
25
26 /// This represents a trait whose name we could not resolve.
27 const UNKNOWN_TRAIT: chalk_ir::TraitId =
28     chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() });
29
30 pub(super) trait ToChalk {
31     type Chalk;
32     fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk;
33     fn from_chalk(db: &impl HirDatabase, chalk: Self::Chalk) -> Self;
34 }
35
36 pub(super) fn from_chalk<T, ChalkT>(db: &impl HirDatabase, chalk: ChalkT) -> T
37 where
38     T: ToChalk<Chalk = ChalkT>,
39 {
40     T::from_chalk(db, chalk)
41 }
42
43 impl ToChalk for Ty {
44     type Chalk = chalk_ir::Ty;
45     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty {
46         match self {
47             Ty::Apply(apply_ty) => {
48                 let struct_id = apply_ty.ctor.to_chalk(db);
49                 let name = TypeName::TypeKindId(struct_id.into());
50                 let parameters = apply_ty.parameters.to_chalk(db);
51                 chalk_ir::ApplicationTy { name, parameters }.cast()
52             }
53             Ty::Param { idx, .. } => {
54                 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty()
55             }
56             Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize),
57             Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
58             // FIXME this is clearly incorrect, but probably not too incorrect
59             // and I'm not sure what to actually do with Ty::Unknown
60             // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty)
61             Ty::Unknown => {
62                 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty()
63             }
64         }
65     }
66     fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self {
67         match chalk {
68             chalk_ir::Ty::Apply(apply_ty) => {
69                 match apply_ty.name {
70                     TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => {
71                         let ctor = from_chalk(db, struct_id);
72                         let parameters = from_chalk(db, apply_ty.parameters);
73                         Ty::Apply(ApplicationTy { ctor, parameters })
74                     }
75                     // FIXME handle TypeKindId::Trait/Type here
76                     TypeName::TypeKindId(_) => unimplemented!(),
77                     TypeName::AssociatedType(_) => unimplemented!(),
78                     TypeName::Placeholder(idx) => {
79                         assert_eq!(idx.ui, UniverseIndex::ROOT);
80                         Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }
81                     }
82                 }
83             }
84             chalk_ir::Ty::Projection(_) => unimplemented!(),
85             chalk_ir::Ty::UnselectedProjection(_) => unimplemented!(),
86             chalk_ir::Ty::ForAll(_) => unimplemented!(),
87             chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32),
88             chalk_ir::Ty::InferenceVar(_iv) => panic!("unexpected chalk infer ty"),
89         }
90     }
91 }
92
93 impl ToChalk for Substs {
94     type Chalk = Vec<chalk_ir::Parameter>;
95
96     fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter> {
97         self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect()
98     }
99
100     fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs {
101         parameters
102             .into_iter()
103             .map(|p| match p {
104                 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty),
105                 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(),
106             })
107             .collect::<Vec<_>>()
108             .into()
109     }
110 }
111
112 impl ToChalk for TraitRef {
113     type Chalk = chalk_ir::TraitRef;
114
115     fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef {
116         let trait_id = self.trait_.to_chalk(db);
117         let parameters = self.substs.to_chalk(db);
118         chalk_ir::TraitRef { trait_id, parameters }
119     }
120
121     fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef) -> Self {
122         let trait_ = from_chalk(db, trait_ref.trait_id);
123         let substs = from_chalk(db, trait_ref.parameters);
124         TraitRef { trait_, substs }
125     }
126 }
127
128 impl ToChalk for Trait {
129     type Chalk = chalk_ir::TraitId;
130
131     fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId {
132         self.id.into()
133     }
134
135     fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> Trait {
136         Trait { id: trait_id.into() }
137     }
138 }
139
140 impl ToChalk for TypeCtor {
141     type Chalk = chalk_ir::StructId;
142
143     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::StructId {
144         db.intern_type_ctor(self).into()
145     }
146
147     fn from_chalk(db: &impl HirDatabase, struct_id: chalk_ir::StructId) -> TypeCtor {
148         db.lookup_intern_type_ctor(struct_id.into())
149     }
150 }
151
152 impl ToChalk for ImplBlock {
153     type Chalk = chalk_ir::ImplId;
154
155     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId {
156         db.intern_impl_block(self).into()
157     }
158
159     fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> ImplBlock {
160         db.lookup_intern_impl_block(impl_id.into())
161     }
162 }
163
164 impl ToChalk for TypeAlias {
165     type Chalk = chalk_ir::TypeId;
166
167     fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId {
168         self.id.into()
169     }
170
171     fn from_chalk(_db: &impl HirDatabase, impl_id: chalk_ir::TypeId) -> TypeAlias {
172         TypeAlias { id: impl_id.into() }
173     }
174 }
175
176 impl ToChalk for GenericPredicate {
177     type Chalk = chalk_ir::QuantifiedWhereClause;
178
179     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause {
180         match self {
181             GenericPredicate::Implemented(trait_ref) => {
182                 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0)
183             }
184             GenericPredicate::Error => {
185                 let impossible_trait_ref = chalk_ir::TraitRef {
186                     trait_id: UNKNOWN_TRAIT,
187                     parameters: vec![Ty::Unknown.to_chalk(db).cast()],
188                 };
189                 make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0)
190             }
191         }
192     }
193
194     fn from_chalk(
195         _db: &impl HirDatabase,
196         _where_clause: chalk_ir::QuantifiedWhereClause,
197     ) -> GenericPredicate {
198         // This should never need to be called
199         unimplemented!()
200     }
201 }
202
203 impl ToChalk for ProjectionTy {
204     type Chalk = chalk_ir::ProjectionTy;
205
206     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy {
207         chalk_ir::ProjectionTy {
208             associated_ty_id: self.associated_ty.to_chalk(db),
209             parameters: self.parameters.to_chalk(db),
210         }
211     }
212
213     fn from_chalk(db: &impl HirDatabase, projection_ty: chalk_ir::ProjectionTy) -> ProjectionTy {
214         ProjectionTy {
215             associated_ty: from_chalk(db, projection_ty.associated_ty_id),
216             parameters: from_chalk(db, projection_ty.parameters),
217         }
218     }
219 }
220
221 impl ToChalk for super::ProjectionPredicate {
222     type Chalk = chalk_ir::Normalize;
223
224     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize {
225         chalk_ir::Normalize {
226             projection: self.projection_ty.to_chalk(db),
227             ty: self.ty.to_chalk(db),
228         }
229     }
230
231     fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self {
232         unimplemented!()
233     }
234 }
235
236 impl ToChalk for Obligation {
237     type Chalk = chalk_ir::DomainGoal;
238
239     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal {
240         match self {
241             Obligation::Trait(tr) => tr.to_chalk(db).cast(),
242             Obligation::Projection(pr) => pr.to_chalk(db).cast(),
243         }
244     }
245
246     fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal) -> Self {
247         unimplemented!()
248     }
249 }
250
251 impl<T> ToChalk for Canonical<T>
252 where
253     T: ToChalk,
254 {
255     type Chalk = chalk_ir::Canonical<T::Chalk>;
256
257     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
258         let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT);
259         let value = self.value.to_chalk(db);
260         let canonical = chalk_ir::Canonical { value, binders: vec![parameter; self.num_vars] };
261         canonical
262     }
263
264     fn from_chalk(db: &impl HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
265         Canonical { num_vars: canonical.binders.len(), value: from_chalk(db, canonical.value) }
266     }
267 }
268
269 impl ToChalk for Arc<super::TraitEnvironment> {
270     type Chalk = Arc<chalk_ir::Environment>;
271
272     fn to_chalk(self, db: &impl HirDatabase) -> Arc<chalk_ir::Environment> {
273         let mut clauses = Vec::new();
274         for pred in &self.predicates {
275             if pred.is_error() {
276                 // for env, we just ignore errors
277                 continue;
278             }
279             clauses.push(pred.clone().to_chalk(db).cast());
280         }
281         chalk_ir::Environment::new().add_clauses(clauses)
282     }
283
284     fn from_chalk(
285         _db: &impl HirDatabase,
286         _env: Arc<chalk_ir::Environment>,
287     ) -> Arc<super::TraitEnvironment> {
288         unimplemented!()
289     }
290 }
291
292 impl<T: ToChalk> ToChalk for super::InEnvironment<T> {
293     type Chalk = chalk_ir::InEnvironment<T::Chalk>;
294
295     fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
296         chalk_ir::InEnvironment {
297             environment: self.environment.to_chalk(db),
298             goal: self.value.to_chalk(db),
299         }
300     }
301
302     fn from_chalk(
303         db: &impl HirDatabase,
304         in_env: chalk_ir::InEnvironment<T::Chalk>,
305     ) -> super::InEnvironment<T> {
306         super::InEnvironment {
307             environment: from_chalk(db, in_env.environment),
308             value: from_chalk(db, in_env.goal),
309         }
310     }
311 }
312
313 fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> {
314     chalk_ir::Binders {
315         value,
316         binders: std::iter::repeat(chalk_ir::ParameterKind::Ty(())).take(num_vars).collect(),
317     }
318 }
319
320 fn is_non_enumerable_trait(db: &impl HirDatabase, trait_: Trait) -> bool {
321     let name = trait_.name(db).unwrap_or_else(crate::Name::missing).to_string();
322     match &*name {
323         "Sized" => true,
324         _ => false,
325     }
326 }
327
328 fn convert_where_clauses(
329     db: &impl HirDatabase,
330     def: GenericDef,
331     substs: &Substs,
332 ) -> Vec<chalk_ir::QuantifiedWhereClause> {
333     let generic_predicates = db.generic_predicates(def);
334     let mut result = Vec::with_capacity(generic_predicates.len());
335     for pred in generic_predicates.iter() {
336         if pred.is_error() {
337             // HACK: Return just the single predicate (which is always false
338             // anyway), otherwise Chalk can easily get into slow situations
339             return vec![pred.clone().subst(substs).to_chalk(db)];
340         }
341         result.push(pred.clone().subst(substs).to_chalk(db));
342     }
343     result
344 }
345
346 impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB>
347 where
348     DB: HirDatabase,
349 {
350     fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum> {
351         self.db.associated_ty_data(id)
352     }
353     fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> {
354         self.db.trait_datum(self.krate, trait_id)
355     }
356     fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> {
357         self.db.struct_datum(self.krate, struct_id)
358     }
359     fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
360         self.db.impl_datum(self.krate, impl_id)
361     }
362     fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> {
363         debug!("impls_for_trait {:?}", trait_id);
364         if trait_id == UNKNOWN_TRAIT {
365             return Vec::new();
366         }
367         let trait_: Trait = from_chalk(self.db, trait_id);
368         let result: Vec<_> = self
369             .db
370             .impls_for_trait(self.krate, trait_)
371             .iter()
372             .map(|impl_block| impl_block.to_chalk(self.db))
373             .collect();
374         debug!("impls_for_trait returned {} impls", result.len());
375         result
376     }
377     fn impl_provided_for(
378         &self,
379         auto_trait_id: chalk_ir::TraitId,
380         struct_id: chalk_ir::StructId,
381     ) -> bool {
382         debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id);
383         false // FIXME
384     }
385     fn type_name(&self, _id: TypeKindId) -> Identifier {
386         unimplemented!()
387     }
388     fn split_projection<'p>(
389         &self,
390         projection: &'p chalk_ir::ProjectionTy,
391     ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) {
392         debug!("split_projection {:?}", projection);
393         unimplemented!()
394     }
395     fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause> {
396         debug!("custom_clauses");
397         vec![]
398     }
399     fn all_structs(&self) -> Vec<chalk_ir::StructId> {
400         debug!("all_structs");
401         // FIXME
402         vec![]
403     }
404 }
405
406 pub(crate) fn associated_ty_data_query(
407     db: &impl HirDatabase,
408     id: TypeId,
409 ) -> Arc<AssociatedTyDatum> {
410     debug!("associated_ty_data {:?}", id);
411     let type_alias: TypeAlias = from_chalk(db, id);
412     let trait_ = match type_alias.container(db) {
413         Some(crate::Container::Trait(t)) => t,
414         _ => panic!("associated type not in trait"),
415     };
416     let generic_params = type_alias.generic_params(db);
417     let parameter_kinds = generic_params
418         .params_including_parent()
419         .into_iter()
420         .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string())))
421         .collect();
422     let datum = AssociatedTyDatum {
423         trait_id: trait_.to_chalk(db),
424         id,
425         name: lalrpop_intern::intern(&type_alias.name(db).to_string()),
426         parameter_kinds,
427         // FIXME add bounds and where clauses
428         bounds: vec![],
429         where_clauses: vec![],
430     };
431     Arc::new(datum)
432 }
433
434 pub(crate) fn trait_datum_query(
435     db: &impl HirDatabase,
436     krate: Crate,
437     trait_id: chalk_ir::TraitId,
438 ) -> Arc<TraitDatum> {
439     debug!("trait_datum {:?}", trait_id);
440     if trait_id == UNKNOWN_TRAIT {
441         let trait_datum_bound = chalk_rust_ir::TraitDatumBound {
442             trait_ref: chalk_ir::TraitRef {
443                 trait_id: UNKNOWN_TRAIT,
444                 parameters: vec![chalk_ir::Ty::BoundVar(0).cast()],
445             },
446             associated_ty_ids: Vec::new(),
447             where_clauses: Vec::new(),
448             flags: chalk_rust_ir::TraitFlags {
449                 non_enumerable: false,
450                 auto: false,
451                 marker: false,
452                 upstream: true,
453                 fundamental: false,
454             },
455         };
456         return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) });
457     }
458     let trait_: Trait = from_chalk(db, trait_id);
459     debug!("trait {:?} = {:?}", trait_id, trait_.name(db));
460     let generic_params = trait_.generic_params(db);
461     let bound_vars = Substs::bound_vars(&generic_params);
462     let trait_ref = trait_.trait_ref(db).subst(&bound_vars).to_chalk(db);
463     let flags = chalk_rust_ir::TraitFlags {
464         auto: trait_.is_auto(db),
465         upstream: trait_.module(db).krate(db) != Some(krate),
466         non_enumerable: is_non_enumerable_trait(db, trait_),
467         // FIXME set these flags correctly
468         marker: false,
469         fundamental: false,
470     };
471     let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
472     let associated_ty_ids = trait_
473         .items(db)
474         .into_iter()
475         .filter_map(|trait_item| match trait_item {
476             crate::traits::TraitItem::TypeAlias(type_alias) => Some(type_alias),
477             _ => None,
478         })
479         .map(|type_alias| type_alias.to_chalk(db))
480         .collect();
481     let trait_datum_bound =
482         chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids };
483     let trait_datum = TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()) };
484     Arc::new(trait_datum)
485 }
486
487 pub(crate) fn struct_datum_query(
488     db: &impl HirDatabase,
489     krate: Crate,
490     struct_id: chalk_ir::StructId,
491 ) -> Arc<StructDatum> {
492     debug!("struct_datum {:?}", struct_id);
493     let type_ctor = from_chalk(db, struct_id);
494     debug!("struct {:?} = {:?}", struct_id, type_ctor);
495     // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor
496     // FIXME extract this to a method on Ty
497     let (num_params, where_clauses, upstream) = match type_ctor {
498         TypeCtor::Bool
499         | TypeCtor::Char
500         | TypeCtor::Int(_)
501         | TypeCtor::Float(_)
502         | TypeCtor::Never
503         | TypeCtor::Str => (0, vec![], true),
504         TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => {
505             (1, vec![], true)
506         }
507         TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true),
508         TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true),
509         TypeCtor::FnDef(callable) => {
510             tested_by!(trait_resolution_on_fn_type);
511             let upstream = match callable {
512                 CallableDef::Function(f) => f.module(db).krate(db),
513                 CallableDef::Struct(s) => s.module(db).krate(db),
514                 CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db),
515             } != Some(krate);
516             let generic_def: GenericDef = callable.into();
517             let generic_params = generic_def.generic_params(db);
518             let bound_vars = Substs::bound_vars(&generic_params);
519             let where_clauses = convert_where_clauses(db, generic_def, &bound_vars);
520             (generic_params.count_params_including_parent(), where_clauses, upstream)
521         }
522         TypeCtor::Adt(adt) => {
523             let generic_params = adt.generic_params(db);
524             let bound_vars = Substs::bound_vars(&generic_params);
525             let where_clauses = convert_where_clauses(db, adt.into(), &bound_vars);
526             (
527                 generic_params.count_params_including_parent(),
528                 where_clauses,
529                 adt.krate(db) != Some(krate),
530             )
531         }
532     };
533     let flags = chalk_rust_ir::StructFlags {
534         upstream,
535         // FIXME set fundamental flag correctly
536         fundamental: false,
537     };
538     let self_ty = chalk_ir::ApplicationTy {
539         name: TypeName::TypeKindId(type_ctor.to_chalk(db).into()),
540         parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(),
541     };
542     let struct_datum_bound = chalk_rust_ir::StructDatumBound {
543         self_ty,
544         fields: Vec::new(), // FIXME add fields (only relevant for auto traits)
545         where_clauses,
546         flags,
547     };
548     let struct_datum = StructDatum { binders: make_binders(struct_datum_bound, num_params) };
549     Arc::new(struct_datum)
550 }
551
552 pub(crate) fn impl_datum_query(
553     db: &impl HirDatabase,
554     krate: Crate,
555     impl_id: ImplId,
556 ) -> Arc<ImplDatum> {
557     let _p = ra_prof::profile("impl_datum");
558     debug!("impl_datum {:?}", impl_id);
559     let impl_block: ImplBlock = from_chalk(db, impl_id);
560     let generic_params = impl_block.generic_params(db);
561     let bound_vars = Substs::bound_vars(&generic_params);
562     let trait_ref = impl_block
563         .target_trait_ref(db)
564         .expect("FIXME handle unresolved impl block trait ref")
565         .subst(&bound_vars);
566     let impl_type = if impl_block.module().krate(db) == Some(krate) {
567         chalk_rust_ir::ImplType::Local
568     } else {
569         chalk_rust_ir::ImplType::External
570     };
571     let where_clauses = convert_where_clauses(db, impl_block.into(), &bound_vars);
572     let negative = impl_block.is_negative(db);
573     debug!(
574         "impl {:?}: {}{} where {:?}",
575         impl_id,
576         if negative { "!" } else { "" },
577         trait_ref.display(db),
578         where_clauses
579     );
580     let trait_ = trait_ref.trait_;
581     let trait_ref = trait_ref.to_chalk(db);
582     let associated_ty_values = impl_block
583         .items(db)
584         .into_iter()
585         .filter_map(|item| match item {
586             ImplItem::TypeAlias(t) => Some(t),
587             _ => None,
588         })
589         .filter_map(|t| {
590             let assoc_ty = trait_.associated_type_by_name(db, t.name(db))?;
591             let ty = db.type_for_def(t.into(), crate::Namespace::Types).subst(&bound_vars);
592             Some(chalk_rust_ir::AssociatedTyValue {
593                 impl_id,
594                 associated_ty_id: assoc_ty.to_chalk(db),
595                 value: chalk_ir::Binders {
596                     value: chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) },
597                     binders: vec![], // we don't support GATs yet
598                 },
599             })
600         })
601         .collect();
602
603     let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
604         trait_ref: if negative {
605             chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref)
606         } else {
607             chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref)
608         },
609         where_clauses,
610         associated_ty_values,
611         impl_type,
612     };
613     debug!("impl_datum: {:?}", impl_datum_bound);
614     let impl_datum = ImplDatum { binders: make_binders(impl_datum_bound, bound_vars.len()) };
615     Arc::new(impl_datum)
616 }
617
618 fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T {
619     T::from_intern_id(InternId::from(chalk_id.index))
620 }
621 fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
622     chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
623 }
624
625 impl From<chalk_ir::TraitId> for crate::ids::TraitId {
626     fn from(trait_id: chalk_ir::TraitId) -> Self {
627         id_from_chalk(trait_id.0)
628     }
629 }
630
631 impl From<crate::ids::TraitId> for chalk_ir::TraitId {
632     fn from(trait_id: crate::ids::TraitId) -> Self {
633         chalk_ir::TraitId(id_to_chalk(trait_id))
634     }
635 }
636
637 impl From<chalk_ir::TypeId> for crate::ids::TypeAliasId {
638     fn from(type_id: chalk_ir::TypeId) -> Self {
639         id_from_chalk(type_id.0)
640     }
641 }
642
643 impl From<crate::ids::TypeAliasId> for chalk_ir::TypeId {
644     fn from(type_id: crate::ids::TypeAliasId) -> Self {
645         chalk_ir::TypeId(id_to_chalk(type_id))
646     }
647 }
648
649 impl From<chalk_ir::StructId> for crate::ids::TypeCtorId {
650     fn from(struct_id: chalk_ir::StructId) -> Self {
651         id_from_chalk(struct_id.0)
652     }
653 }
654
655 impl From<crate::ids::TypeCtorId> for chalk_ir::StructId {
656     fn from(type_ctor_id: crate::ids::TypeCtorId) -> Self {
657         chalk_ir::StructId(id_to_chalk(type_ctor_id))
658     }
659 }
660
661 impl From<chalk_ir::ImplId> for crate::ids::GlobalImplId {
662     fn from(impl_id: chalk_ir::ImplId) -> Self {
663         id_from_chalk(impl_id.0)
664     }
665 }
666
667 impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId {
668     fn from(impl_id: crate::ids::GlobalImplId) -> Self {
669         chalk_ir::ImplId(id_to_chalk(impl_id))
670     }
671 }