aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/mapping.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-04-09 13:11:37 +0100
committerFlorian Diebold <[email protected]>2021-04-09 13:11:37 +0100
commit743faa21e74cc5b627935e2c4c3365807a5c722f (patch)
tree28504dbaaa7238c5d7d64d2371dc3b672cb21e16 /crates/hir_ty/src/mapping.rs
parent99ed68a109c9f7e0dc6a82ccb5bf854d60943957 (diff)
Reorganize hir_ty modules
Chalk isn't really a 'traits' thing anymore, so it doesn't make sense to have all the Chalk-related stuff in submodules of `traits`.
Diffstat (limited to 'crates/hir_ty/src/mapping.rs')
-rw-r--r--crates/hir_ty/src/mapping.rs125
1 files changed, 125 insertions, 0 deletions
diff --git a/crates/hir_ty/src/mapping.rs b/crates/hir_ty/src/mapping.rs
new file mode 100644
index 000000000..4d3c41b2c
--- /dev/null
+++ b/crates/hir_ty/src/mapping.rs
@@ -0,0 +1,125 @@
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
6use chalk_ir::{DebruijnIndex, cast::Cast, fold::Shift};
7use chalk_solve::rust_ir;
8
9use base_db::salsa::InternKey;
10use hir_def::{GenericDefId, TypeAliasId};
11
12use crate::{AliasEq, AliasTy, CallableDefId, FnDefId, Interner, ProjectionTyExt, QuantifiedWhereClause, Substitution, Ty, WhereClause, chalk_db::{self, ToChalk}, db::HirDatabase};
13
14impl ToChalk for hir_def::TraitId {
15 type Chalk = chalk_db::TraitId;
16
17 fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::TraitId {
18 chalk_ir::TraitId(self.as_intern_id())
19 }
20
21 fn from_chalk(_db: &dyn HirDatabase, trait_id: chalk_db::TraitId) -> hir_def::TraitId {
22 InternKey::from_intern_id(trait_id.0)
23 }
24}
25
26impl ToChalk for hir_def::ImplId {
27 type Chalk = chalk_db::ImplId;
28
29 fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::ImplId {
30 chalk_ir::ImplId(self.as_intern_id())
31 }
32
33 fn from_chalk(_db: &dyn HirDatabase, impl_id: chalk_db::ImplId) -> hir_def::ImplId {
34 InternKey::from_intern_id(impl_id.0)
35 }
36}
37
38impl ToChalk for CallableDefId {
39 type Chalk = FnDefId;
40
41 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId {
42 db.intern_callable_def(self).into()
43 }
44
45 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
46 db.lookup_intern_callable_def(fn_def_id.into())
47 }
48}
49
50pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId);
51
52impl ToChalk for TypeAliasAsValue {
53 type Chalk = chalk_db::AssociatedTyValueId;
54
55 fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::AssociatedTyValueId {
56 rust_ir::AssociatedTyValueId(self.0.as_intern_id())
57 }
58
59 fn from_chalk(
60 _db: &dyn HirDatabase,
61 assoc_ty_value_id: chalk_db::AssociatedTyValueId,
62 ) -> TypeAliasAsValue {
63 TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0))
64 }
65}
66
67pub(super) fn convert_where_clauses(
68 db: &dyn HirDatabase,
69 def: GenericDefId,
70 substs: &Substitution,
71) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> {
72 let generic_predicates = db.generic_predicates(def);
73 let mut result = Vec::with_capacity(generic_predicates.len());
74 for pred in generic_predicates.iter() {
75 result.push(pred.clone().substitute(&Interner, substs));
76 }
77 result
78}
79
80pub(super) fn generic_predicate_to_inline_bound(
81 db: &dyn HirDatabase,
82 pred: &QuantifiedWhereClause,
83 self_ty: &Ty,
84) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
85 // An InlineBound is like a GenericPredicate, except the self type is left out.
86 // We don't have a special type for this, but Chalk does.
87 let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE);
88 let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
89 match pred {
90 WhereClause::Implemented(trait_ref) => {
91 if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in {
92 // we can only convert predicates back to type bounds if they
93 // have the expected self type
94 return None;
95 }
96 let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..]
97 .iter()
98 .map(|ty| ty.clone().cast(&Interner))
99 .collect();
100 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
101 Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
102 }
103 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
104 if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in {
105 return None;
106 }
107 let trait_ = projection_ty.trait_(db);
108 let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..]
109 .iter()
110 .map(|ty| ty.clone().cast(&Interner))
111 .collect();
112 let alias_eq_bound = rust_ir::AliasEqBound {
113 value: ty.clone(),
114 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self },
115 associated_ty_id: projection_ty.associated_ty_id,
116 parameters: Vec::new(), // FIXME we don't support generic associated types yet
117 };
118 Some(chalk_ir::Binders::new(
119 binders,
120 rust_ir::InlineBound::AliasEqBound(alias_eq_bound),
121 ))
122 }
123 _ => None,
124 }
125}