hir_ty/
mapping.rs

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 hir_def::{LifetimeParamId, TraitId, TypeAliasId, TypeOrConstParamId};
7use salsa::{
8    Id,
9    plumbing::{AsId, FromId},
10};
11
12use crate::{
13    AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, Interner, OpaqueTyId,
14    PlaceholderIndex, chalk_db,
15    db::{HirDatabase, InternedLifetimeParamId, InternedTypeOrConstParamId},
16};
17
18pub trait ToChalk {
19    type Chalk;
20    fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk;
21    fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self;
22}
23
24pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T
25where
26    T: ToChalk<Chalk = ChalkT>,
27{
28    T::from_chalk(db, chalk)
29}
30
31impl ToChalk for hir_def::ImplId {
32    type Chalk = chalk_db::ImplId;
33
34    fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::ImplId {
35        chalk_ir::ImplId(self.as_id())
36    }
37
38    fn from_chalk(_db: &dyn HirDatabase, impl_id: chalk_db::ImplId) -> hir_def::ImplId {
39        FromId::from_id(impl_id.0.as_id())
40    }
41}
42
43impl ToChalk for CallableDefId {
44    type Chalk = FnDefId;
45
46    fn to_chalk(self, _db: &dyn HirDatabase) -> FnDefId {
47        chalk_ir::FnDefId(salsa::plumbing::AsId::as_id(&self))
48    }
49
50    fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
51        salsa::plumbing::FromIdWithDb::from_id(fn_def_id.0, db.zalsa())
52    }
53}
54
55impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
56    fn from(id: OpaqueTyId) -> Self {
57        FromId::from_id(id.0)
58    }
59}
60
61impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
62    fn from(id: crate::db::InternedOpaqueTyId) -> Self {
63        chalk_ir::OpaqueTyId(id.as_id())
64    }
65}
66
67impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
68    fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
69        FromId::from_id(id.0)
70    }
71}
72
73impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
74    fn from(id: crate::db::InternedClosureId) -> Self {
75        chalk_ir::ClosureId(id.as_id())
76    }
77}
78
79impl From<chalk_ir::CoroutineId<Interner>> for crate::db::InternedCoroutineId {
80    fn from(id: chalk_ir::CoroutineId<Interner>) -> Self {
81        Self::from_id(id.0)
82    }
83}
84
85impl From<crate::db::InternedCoroutineId> for chalk_ir::CoroutineId<Interner> {
86    fn from(id: crate::db::InternedCoroutineId) -> Self {
87        chalk_ir::CoroutineId(id.as_id())
88    }
89}
90
91pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
92    chalk_ir::ForeignDefId(id.as_id())
93}
94
95pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
96    FromId::from_id(id.0)
97}
98
99pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
100    chalk_ir::AssocTypeId(id.as_id())
101}
102
103pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
104    FromId::from_id(id.0)
105}
106
107pub fn from_placeholder_idx(
108    db: &dyn HirDatabase,
109    idx: PlaceholderIndex,
110) -> (TypeOrConstParamId, u32) {
111    assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
112    // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
113    let interned_id =
114        InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) });
115    interned_id.loc(db)
116}
117
118pub fn to_placeholder_idx(
119    db: &dyn HirDatabase,
120    id: TypeOrConstParamId,
121    idx: u32,
122) -> PlaceholderIndex {
123    let interned_id = InternedTypeOrConstParamId::new(db, (id, idx));
124    PlaceholderIndex {
125        ui: chalk_ir::UniverseIndex::ROOT,
126        idx: interned_id.as_id().index() as usize,
127    }
128}
129
130pub fn to_placeholder_idx_no_index(
131    db: &dyn HirDatabase,
132    id: TypeOrConstParamId,
133) -> PlaceholderIndex {
134    let index = crate::generics::generics(db, id.parent)
135        .type_or_const_param_idx(id)
136        .expect("param not found");
137    to_placeholder_idx(db, id, index as u32)
138}
139
140pub fn lt_from_placeholder_idx(
141    db: &dyn HirDatabase,
142    idx: PlaceholderIndex,
143) -> (LifetimeParamId, u32) {
144    assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
145    // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
146    let interned_id =
147        InternedLifetimeParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) });
148    interned_id.loc(db)
149}
150
151pub fn lt_to_placeholder_idx(
152    db: &dyn HirDatabase,
153    id: LifetimeParamId,
154    idx: u32,
155) -> PlaceholderIndex {
156    let interned_id = InternedLifetimeParamId::new(db, (id, idx));
157    PlaceholderIndex {
158        ui: chalk_ir::UniverseIndex::ROOT,
159        idx: interned_id.as_id().index() as usize,
160    }
161}
162
163pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
164    chalk_ir::TraitId(id.as_id())
165}
166
167pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
168    FromId::from_id(id.0)
169}