1use hir_def::{
4 AdtId, AttrDefId, CallableDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
5 GeneralConstId, GenericDefId, HasModule, ImplId, ModuleId, StaticId, StructId, TraitId,
6 TypeAliasId, UnionId, db::DefDatabase,
7};
8use rustc_type_ir::inherent;
9use stdx::impl_from;
10
11use crate::db::{InternedClosureId, InternedCoroutineId, InternedOpaqueTyId};
12
13use super::DbInterner;
14
15#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
16pub enum Ctor {
17 Struct(StructId),
18 Enum(EnumVariantId),
19}
20
21#[derive(PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
22pub enum SolverDefId {
23 AdtId(AdtId),
24 ConstId(ConstId),
25 FunctionId(FunctionId),
26 ImplId(ImplId),
27 StaticId(StaticId),
28 TraitId(TraitId),
29 TypeAliasId(TypeAliasId),
30 InternedClosureId(InternedClosureId),
31 InternedCoroutineId(InternedCoroutineId),
32 InternedOpaqueTyId(InternedOpaqueTyId),
33 EnumVariantId(EnumVariantId),
34 Ctor(Ctor),
36}
37
38impl std::fmt::Debug for SolverDefId {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 let interner = DbInterner::conjure();
41 let db = interner.db;
42 match *self {
43 SolverDefId::AdtId(AdtId::StructId(id)) => {
44 f.debug_tuple("AdtId").field(&db.struct_signature(id).name.as_str()).finish()
45 }
46 SolverDefId::AdtId(AdtId::EnumId(id)) => {
47 f.debug_tuple("AdtId").field(&db.enum_signature(id).name.as_str()).finish()
48 }
49 SolverDefId::AdtId(AdtId::UnionId(id)) => {
50 f.debug_tuple("AdtId").field(&db.union_signature(id).name.as_str()).finish()
51 }
52 SolverDefId::ConstId(id) => f
53 .debug_tuple("ConstId")
54 .field(&db.const_signature(id).name.as_ref().map_or("_", |name| name.as_str()))
55 .finish(),
56 SolverDefId::FunctionId(id) => {
57 f.debug_tuple("FunctionId").field(&db.function_signature(id).name.as_str()).finish()
58 }
59 SolverDefId::ImplId(id) => f.debug_tuple("ImplId").field(&id).finish(),
60 SolverDefId::StaticId(id) => {
61 f.debug_tuple("StaticId").field(&db.static_signature(id).name.as_str()).finish()
62 }
63 SolverDefId::TraitId(id) => {
64 f.debug_tuple("TraitId").field(&db.trait_signature(id).name.as_str()).finish()
65 }
66 SolverDefId::TypeAliasId(id) => f
67 .debug_tuple("TypeAliasId")
68 .field(&db.type_alias_signature(id).name.as_str())
69 .finish(),
70 SolverDefId::InternedClosureId(id) => {
71 f.debug_tuple("InternedClosureId").field(&id).finish()
72 }
73 SolverDefId::InternedCoroutineId(id) => {
74 f.debug_tuple("InternedCoroutineId").field(&id).finish()
75 }
76 SolverDefId::InternedOpaqueTyId(id) => {
77 f.debug_tuple("InternedOpaqueTyId").field(&id).finish()
78 }
79 SolverDefId::EnumVariantId(id) => {
80 let parent_enum = id.loc(db).parent;
81 f.debug_tuple("EnumVariantId")
82 .field(&format_args!(
83 "\"{}::{}\"",
84 db.enum_signature(parent_enum).name.as_str(),
85 parent_enum.enum_variants(db).variant_name_by_id(id).unwrap().as_str()
86 ))
87 .finish()
88 }
89 SolverDefId::Ctor(Ctor::Struct(id)) => {
90 f.debug_tuple("Ctor").field(&db.struct_signature(id).name.as_str()).finish()
91 }
92 SolverDefId::Ctor(Ctor::Enum(id)) => {
93 let parent_enum = id.loc(db).parent;
94 f.debug_tuple("Ctor")
95 .field(&format_args!(
96 "\"{}::{}\"",
97 db.enum_signature(parent_enum).name.as_str(),
98 parent_enum.enum_variants(db).variant_name_by_id(id).unwrap().as_str()
99 ))
100 .finish()
101 }
102 }
103 }
104}
105
106impl_from!(
107 AdtId(StructId, EnumId, UnionId),
108 ConstId,
109 FunctionId,
110 ImplId,
111 StaticId,
112 TraitId,
113 TypeAliasId,
114 InternedClosureId,
115 InternedCoroutineId,
116 InternedOpaqueTyId,
117 EnumVariantId,
118 Ctor
119 for SolverDefId
120);
121
122impl From<GenericDefId> for SolverDefId {
123 fn from(value: GenericDefId) -> Self {
124 match value {
125 GenericDefId::AdtId(adt_id) => SolverDefId::AdtId(adt_id),
126 GenericDefId::ConstId(const_id) => SolverDefId::ConstId(const_id),
127 GenericDefId::FunctionId(function_id) => SolverDefId::FunctionId(function_id),
128 GenericDefId::ImplId(impl_id) => SolverDefId::ImplId(impl_id),
129 GenericDefId::StaticId(static_id) => SolverDefId::StaticId(static_id),
130 GenericDefId::TraitId(trait_id) => SolverDefId::TraitId(trait_id),
131 GenericDefId::TypeAliasId(type_alias_id) => SolverDefId::TypeAliasId(type_alias_id),
132 }
133 }
134}
135
136impl From<GeneralConstId> for SolverDefId {
137 #[inline]
138 fn from(value: GeneralConstId) -> Self {
139 match value {
140 GeneralConstId::ConstId(const_id) => SolverDefId::ConstId(const_id),
141 GeneralConstId::StaticId(static_id) => SolverDefId::StaticId(static_id),
142 }
143 }
144}
145
146impl From<DefWithBodyId> for SolverDefId {
147 #[inline]
148 fn from(value: DefWithBodyId) -> Self {
149 match value {
150 DefWithBodyId::FunctionId(id) => id.into(),
151 DefWithBodyId::StaticId(id) => id.into(),
152 DefWithBodyId::ConstId(id) => id.into(),
153 DefWithBodyId::VariantId(id) => id.into(),
154 }
155 }
156}
157
158impl TryFrom<SolverDefId> for AttrDefId {
159 type Error = ();
160 #[inline]
161 fn try_from(value: SolverDefId) -> Result<Self, Self::Error> {
162 match value {
163 SolverDefId::AdtId(it) => Ok(it.into()),
164 SolverDefId::ConstId(it) => Ok(it.into()),
165 SolverDefId::FunctionId(it) => Ok(it.into()),
166 SolverDefId::ImplId(it) => Ok(it.into()),
167 SolverDefId::StaticId(it) => Ok(it.into()),
168 SolverDefId::TraitId(it) => Ok(it.into()),
169 SolverDefId::TypeAliasId(it) => Ok(it.into()),
170 SolverDefId::EnumVariantId(it) => Ok(it.into()),
171 SolverDefId::Ctor(Ctor::Struct(it)) => Ok(it.into()),
172 SolverDefId::Ctor(Ctor::Enum(it)) => Ok(it.into()),
173 SolverDefId::InternedClosureId(_)
174 | SolverDefId::InternedCoroutineId(_)
175 | SolverDefId::InternedOpaqueTyId(_) => Err(()),
176 }
177 }
178}
179
180impl TryFrom<SolverDefId> for DefWithBodyId {
181 type Error = ();
182
183 #[inline]
184 fn try_from(value: SolverDefId) -> Result<Self, Self::Error> {
185 let id = match value {
186 SolverDefId::ConstId(id) => id.into(),
187 SolverDefId::FunctionId(id) => id.into(),
188 SolverDefId::StaticId(id) => id.into(),
189 SolverDefId::EnumVariantId(id) | SolverDefId::Ctor(Ctor::Enum(id)) => id.into(),
190 SolverDefId::InternedOpaqueTyId(_)
191 | SolverDefId::TraitId(_)
192 | SolverDefId::TypeAliasId(_)
193 | SolverDefId::ImplId(_)
194 | SolverDefId::InternedClosureId(_)
195 | SolverDefId::InternedCoroutineId(_)
196 | SolverDefId::Ctor(Ctor::Struct(_))
197 | SolverDefId::AdtId(_) => return Err(()),
198 };
199 Ok(id)
200 }
201}
202
203impl TryFrom<SolverDefId> for GenericDefId {
204 type Error = ();
205
206 fn try_from(value: SolverDefId) -> Result<Self, Self::Error> {
207 Ok(match value {
208 SolverDefId::AdtId(adt_id) => GenericDefId::AdtId(adt_id),
209 SolverDefId::ConstId(const_id) => GenericDefId::ConstId(const_id),
210 SolverDefId::FunctionId(function_id) => GenericDefId::FunctionId(function_id),
211 SolverDefId::ImplId(impl_id) => GenericDefId::ImplId(impl_id),
212 SolverDefId::StaticId(static_id) => GenericDefId::StaticId(static_id),
213 SolverDefId::TraitId(trait_id) => GenericDefId::TraitId(trait_id),
214 SolverDefId::TypeAliasId(type_alias_id) => GenericDefId::TypeAliasId(type_alias_id),
215 SolverDefId::InternedClosureId(_)
216 | SolverDefId::InternedCoroutineId(_)
217 | SolverDefId::InternedOpaqueTyId(_)
218 | SolverDefId::EnumVariantId(_)
219 | SolverDefId::Ctor(_) => return Err(()),
220 })
221 }
222}
223
224impl SolverDefId {
225 #[inline]
226 #[track_caller]
227 pub fn expect_opaque_ty(self) -> InternedOpaqueTyId {
228 match self {
229 SolverDefId::InternedOpaqueTyId(it) => it,
230 _ => panic!("expected opaque type, found {self:?}"),
231 }
232 }
233
234 #[inline]
235 #[track_caller]
236 pub fn expect_type_alias(self) -> TypeAliasId {
237 match self {
238 SolverDefId::TypeAliasId(it) => it,
239 _ => panic!("expected type alias, found {self:?}"),
240 }
241 }
242}
243
244impl HasModule for SolverDefId {
245 fn module(&self, db: &dyn DefDatabase) -> ModuleId {
246 match *self {
247 SolverDefId::AdtId(id) => id.module(db),
248 SolverDefId::ConstId(id) => id.module(db),
249 SolverDefId::FunctionId(id) => id.module(db),
250 SolverDefId::ImplId(id) => id.module(db),
251 SolverDefId::StaticId(id) => id.module(db),
252 SolverDefId::TraitId(id) => id.module(db),
253 SolverDefId::TypeAliasId(id) => id.module(db),
254 SolverDefId::InternedClosureId(id) => id.loc(db).0.module(db),
255 SolverDefId::InternedCoroutineId(id) => id.loc(db).0.module(db),
256 SolverDefId::InternedOpaqueTyId(id) => match id.loc(db) {
257 crate::ImplTraitId::ReturnTypeImplTrait(owner, _) => owner.module(db),
258 crate::ImplTraitId::TypeAliasImplTrait(owner, _) => owner.module(db),
259 },
260 SolverDefId::Ctor(Ctor::Enum(id)) | SolverDefId::EnumVariantId(id) => id.module(db),
261 SolverDefId::Ctor(Ctor::Struct(id)) => id.module(db),
262 }
263 }
264}
265
266impl<'db> inherent::DefId<DbInterner<'db>> for SolverDefId {
267 fn as_local(self) -> Option<SolverDefId> {
268 Some(self)
269 }
270 fn is_local(self) -> bool {
271 true
272 }
273}
274
275macro_rules! declare_id_wrapper {
276 ($name:ident, $wraps:ident) => {
277 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
278 pub struct $name(pub $wraps);
279
280 impl std::fmt::Debug for $name {
281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
282 std::fmt::Debug::fmt(&SolverDefId::from(self.0), f)
283 }
284 }
285
286 impl From<$name> for $wraps {
287 #[inline]
288 fn from(value: $name) -> $wraps {
289 value.0
290 }
291 }
292
293 impl From<$wraps> for $name {
294 #[inline]
295 fn from(value: $wraps) -> $name {
296 Self(value)
297 }
298 }
299
300 impl From<$name> for SolverDefId {
301 #[inline]
302 fn from(value: $name) -> SolverDefId {
303 value.0.into()
304 }
305 }
306
307 impl TryFrom<SolverDefId> for $name {
308 type Error = ();
309
310 #[inline]
311 fn try_from(value: SolverDefId) -> Result<Self, Self::Error> {
312 match value {
313 SolverDefId::$wraps(it) => Ok(Self(it)),
314 _ => Err(()),
315 }
316 }
317 }
318
319 impl<'db> inherent::DefId<DbInterner<'db>> for $name {
320 fn as_local(self) -> Option<SolverDefId> {
321 Some(self.into())
322 }
323 fn is_local(self) -> bool {
324 true
325 }
326 }
327 };
328}
329
330declare_id_wrapper!(TraitIdWrapper, TraitId);
331declare_id_wrapper!(TypeAliasIdWrapper, TypeAliasId);
332declare_id_wrapper!(ClosureIdWrapper, InternedClosureId);
333declare_id_wrapper!(CoroutineIdWrapper, InternedCoroutineId);
334declare_id_wrapper!(AdtIdWrapper, AdtId);
335declare_id_wrapper!(ImplIdWrapper, ImplId);
336
337#[derive(Clone, Copy, PartialEq, Eq, Hash)]
338pub struct GeneralConstIdWrapper(pub GeneralConstId);
339
340impl std::fmt::Debug for GeneralConstIdWrapper {
341 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
342 std::fmt::Debug::fmt(&self.0, f)
343 }
344}
345impl From<GeneralConstIdWrapper> for GeneralConstId {
346 #[inline]
347 fn from(value: GeneralConstIdWrapper) -> GeneralConstId {
348 value.0
349 }
350}
351impl From<GeneralConstId> for GeneralConstIdWrapper {
352 #[inline]
353 fn from(value: GeneralConstId) -> GeneralConstIdWrapper {
354 Self(value)
355 }
356}
357impl From<GeneralConstIdWrapper> for SolverDefId {
358 #[inline]
359 fn from(value: GeneralConstIdWrapper) -> SolverDefId {
360 match value.0 {
361 GeneralConstId::ConstId(id) => SolverDefId::ConstId(id),
362 GeneralConstId::StaticId(id) => SolverDefId::StaticId(id),
363 }
364 }
365}
366impl TryFrom<SolverDefId> for GeneralConstIdWrapper {
367 type Error = ();
368 #[inline]
369 fn try_from(value: SolverDefId) -> Result<Self, Self::Error> {
370 match value {
371 SolverDefId::ConstId(it) => Ok(Self(it.into())),
372 SolverDefId::StaticId(it) => Ok(Self(it.into())),
373 _ => Err(()),
374 }
375 }
376}
377impl<'db> inherent::DefId<DbInterner<'db>> for GeneralConstIdWrapper {
378 fn as_local(self) -> Option<SolverDefId> {
379 Some(self.into())
380 }
381 fn is_local(self) -> bool {
382 true
383 }
384}
385
386#[derive(Clone, Copy, PartialEq, Eq, Hash)]
387pub struct CallableIdWrapper(pub CallableDefId);
388
389impl std::fmt::Debug for CallableIdWrapper {
390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
391 std::fmt::Debug::fmt(&self.0, f)
392 }
393}
394impl From<CallableIdWrapper> for CallableDefId {
395 #[inline]
396 fn from(value: CallableIdWrapper) -> CallableDefId {
397 value.0
398 }
399}
400impl From<CallableDefId> for CallableIdWrapper {
401 #[inline]
402 fn from(value: CallableDefId) -> CallableIdWrapper {
403 Self(value)
404 }
405}
406impl From<CallableIdWrapper> for SolverDefId {
407 #[inline]
408 fn from(value: CallableIdWrapper) -> SolverDefId {
409 match value.0 {
410 CallableDefId::FunctionId(it) => it.into(),
411 CallableDefId::StructId(it) => Ctor::Struct(it).into(),
412 CallableDefId::EnumVariantId(it) => Ctor::Enum(it).into(),
413 }
414 }
415}
416impl TryFrom<SolverDefId> for CallableIdWrapper {
417 type Error = ();
418 #[inline]
419 fn try_from(value: SolverDefId) -> Result<Self, Self::Error> {
420 match value {
421 SolverDefId::FunctionId(it) => Ok(Self(it.into())),
422 SolverDefId::Ctor(Ctor::Struct(it)) => Ok(Self(it.into())),
423 SolverDefId::Ctor(Ctor::Enum(it)) => Ok(Self(it.into())),
424 _ => Err(()),
425 }
426 }
427}
428impl<'db> inherent::DefId<DbInterner<'db>> for CallableIdWrapper {
429 fn as_local(self) -> Option<SolverDefId> {
430 Some(self.into())
431 }
432 fn is_local(self) -> bool {
433 true
434 }
435}