1 //! Provides wrappers over `RustIrDatabase` which record used definitions and write
2 //! `.chalk` files containing those definitions.
3 use std::{
4     borrow::Borrow,
5     cmp::{Ord, Ordering},
6     collections::BTreeSet,
7     fmt::{self, Debug, Display},
8     io::Write,
9     marker::PhantomData,
10     sync::Arc,
11     sync::Mutex,
12 };
13 
14 use crate::rust_ir::*;
15 use crate::{
16     display::{self, WriterState},
17     RustIrDatabase,
18 };
19 use chalk_ir::{interner::Interner, *};
20 
21 mod id_collector;
22 
23 /// Wraps another `RustIrDatabase` (`DB`) and records which definitions are
24 /// used.
25 ///
26 /// A full .chalk file containing all used definitions can be recovered through
27 /// `LoggingRustIrDatabase`'s `Display` implementation.
28 ///
29 /// Uses a separate type, `P`, for the database stored inside to account for
30 /// `Arc` or wrapping other storage mediums.
31 #[derive(Debug)]
32 pub struct LoggingRustIrDatabase<I, DB, P = DB>
33 where
34     DB: RustIrDatabase<I>,
35     P: Borrow<DB>,
36     I: Interner,
37 {
38     ws: WriterState<I, DB, P>,
39     def_ids: Mutex<BTreeSet<RecordedItemId<I>>>,
40     _phantom: PhantomData<DB>,
41 }
42 
43 impl<I, DB, P> LoggingRustIrDatabase<I, DB, P>
44 where
45     DB: RustIrDatabase<I>,
46     P: Borrow<DB>,
47     I: Interner,
48 {
new(db: P) -> Self49     pub fn new(db: P) -> Self {
50         LoggingRustIrDatabase {
51             ws: WriterState::new(db),
52             def_ids: Default::default(),
53             _phantom: PhantomData,
54         }
55     }
56 }
57 
58 impl<I, DB, P> Display for LoggingRustIrDatabase<I, DB, P>
59 where
60     DB: RustIrDatabase<I>,
61     P: Borrow<DB>,
62     I: Interner,
63 {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result64     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65         let def_ids = self.def_ids.lock().unwrap();
66         let stub_ids = id_collector::collect_unrecorded_ids(self.ws.db(), &def_ids);
67         display::write_stub_items(f, &self.ws, stub_ids)?;
68         display::write_items(f, &self.ws, def_ids.iter().copied())
69     }
70 }
71 
72 impl<I, DB, P> LoggingRustIrDatabase<I, DB, P>
73 where
74     DB: RustIrDatabase<I>,
75     P: Borrow<DB>,
76     I: Interner,
77 {
record(&self, id: impl Into<RecordedItemId<I>>)78     fn record(&self, id: impl Into<RecordedItemId<I>>) {
79         self.def_ids.lock().unwrap().insert(id.into());
80     }
81 
record_all<T, U>(&self, ids: T) where T: IntoIterator<Item = U>, U: Into<RecordedItemId<I>>,82     fn record_all<T, U>(&self, ids: T)
83     where
84         T: IntoIterator<Item = U>,
85         U: Into<RecordedItemId<I>>,
86     {
87         self.def_ids
88             .lock()
89             .unwrap()
90             .extend(ids.into_iter().map(Into::into));
91     }
92 }
93 
94 impl<I, DB, P> UnificationDatabase<I> for LoggingRustIrDatabase<I, DB, P>
95 where
96     DB: RustIrDatabase<I>,
97     P: Borrow<DB> + Debug,
98     I: Interner,
99 {
fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I>100     fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I> {
101         self.ws
102             .db()
103             .unification_database()
104             .fn_def_variance(fn_def_id)
105     }
106 
adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I>107     fn adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I> {
108         self.ws.db().unification_database().adt_variance(adt_id)
109     }
110 }
111 
112 impl<I, DB, P> RustIrDatabase<I> for LoggingRustIrDatabase<I, DB, P>
113 where
114     DB: RustIrDatabase<I>,
115     P: Borrow<DB> + Debug,
116     I: Interner,
117 {
custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>>118     fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
119         self.ws.db().custom_clauses()
120     }
121 
associated_ty_data( &self, ty: chalk_ir::AssocTypeId<I>, ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>>122     fn associated_ty_data(
123         &self,
124         ty: chalk_ir::AssocTypeId<I>,
125     ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> {
126         let ty_datum = self.ws.db().associated_ty_data(ty);
127         self.record(ty_datum.trait_id);
128         ty_datum
129     }
130 
trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>>131     fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> {
132         self.record(trait_id);
133         self.ws.db().trait_datum(trait_id)
134     }
135 
adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>>136     fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> {
137         self.record(adt_id);
138         self.ws.db().adt_datum(adt_id)
139     }
140 
generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>>141     fn generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>> {
142         self.record(generator_id);
143         self.ws.db().borrow().generator_datum(generator_id)
144     }
145 
generator_witness_datum( &self, generator_id: GeneratorId<I>, ) -> Arc<GeneratorWitnessDatum<I>>146     fn generator_witness_datum(
147         &self,
148         generator_id: GeneratorId<I>,
149     ) -> Arc<GeneratorWitnessDatum<I>> {
150         self.record(generator_id);
151         self.ws.db().borrow().generator_witness_datum(generator_id)
152     }
153 
adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>>154     fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>> {
155         self.record(id);
156         self.ws.db().adt_repr(id)
157     }
158 
impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>>159     fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> {
160         self.record(impl_id);
161         self.ws.db().impl_datum(impl_id)
162     }
163 
hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I>164     fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> {
165         self.record(id);
166         self.ws.db().hidden_opaque_type(id)
167     }
168 
associated_ty_value( &self, id: crate::rust_ir::AssociatedTyValueId<I>, ) -> Arc<crate::rust_ir::AssociatedTyValue<I>>169     fn associated_ty_value(
170         &self,
171         id: crate::rust_ir::AssociatedTyValueId<I>,
172     ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> {
173         let value = self.ws.db().associated_ty_value(id);
174         self.record(value.impl_id);
175         value
176     }
177 
opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>>178     fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> {
179         self.record(id);
180         self.ws.db().opaque_ty_data(id)
181     }
182 
impls_for_trait( &self, trait_id: TraitId<I>, parameters: &[chalk_ir::GenericArg<I>], binders: &CanonicalVarKinds<I>, ) -> Vec<ImplId<I>>183     fn impls_for_trait(
184         &self,
185         trait_id: TraitId<I>,
186         parameters: &[chalk_ir::GenericArg<I>],
187         binders: &CanonicalVarKinds<I>,
188     ) -> Vec<ImplId<I>> {
189         self.record(trait_id);
190         let impl_ids = self.ws.db().impls_for_trait(trait_id, parameters, binders);
191         self.record_all(impl_ids.iter().copied());
192         impl_ids
193     }
194 
local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>>195     fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>> {
196         self.record(trait_id);
197         self.ws.db().local_impls_to_coherence_check(trait_id)
198     }
199 
impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool200     fn impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool {
201         self.record(auto_trait_id);
202         if let TyKind::Adt(adt_id, _) = ty {
203             self.record(*adt_id);
204         }
205         self.ws.db().impl_provided_for(auto_trait_id, ty)
206     }
207 
well_known_trait_id( &self, well_known_trait: crate::rust_ir::WellKnownTrait, ) -> Option<TraitId<I>>208     fn well_known_trait_id(
209         &self,
210         well_known_trait: crate::rust_ir::WellKnownTrait,
211     ) -> Option<TraitId<I>> {
212         let trait_id = self.ws.db().well_known_trait_id(well_known_trait);
213         trait_id.map(|id| self.record(id));
214         trait_id
215     }
216 
program_clauses_for_env( &self, environment: &chalk_ir::Environment<I>, ) -> chalk_ir::ProgramClauses<I>217     fn program_clauses_for_env(
218         &self,
219         environment: &chalk_ir::Environment<I>,
220     ) -> chalk_ir::ProgramClauses<I> {
221         self.ws.db().program_clauses_for_env(environment)
222     }
223 
interner(&self) -> &I224     fn interner(&self) -> &I {
225         self.ws.db().interner()
226     }
227 
trait_name(&self, trait_id: TraitId<I>) -> String228     fn trait_name(&self, trait_id: TraitId<I>) -> String {
229         self.ws.db().trait_name(trait_id)
230     }
231 
adt_name(&self, adt_id: AdtId<I>) -> String232     fn adt_name(&self, adt_id: AdtId<I>) -> String {
233         self.ws.db().adt_name(adt_id)
234     }
235 
assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String236     fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
237         self.ws.db().assoc_type_name(assoc_ty_id)
238     }
239 
opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String240     fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
241         self.ws.db().opaque_type_name(opaque_ty_id)
242     }
243 
is_object_safe(&self, trait_id: TraitId<I>) -> bool244     fn is_object_safe(&self, trait_id: TraitId<I>) -> bool {
245         self.record(trait_id);
246         self.ws.db().is_object_safe(trait_id)
247     }
248 
fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>>249     fn fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>> {
250         self.record(fn_def_id);
251         self.ws.db().fn_def_datum(fn_def_id)
252     }
253 
fn_def_name(&self, fn_def_id: FnDefId<I>) -> String254     fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
255         self.ws.db().fn_def_name(fn_def_id)
256     }
257 
closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind258     fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind {
259         // TODO: record closure IDs
260         self.ws.db().closure_kind(closure_id, substs)
261     }
262 
closure_inputs_and_output( &self, closure_id: ClosureId<I>, substs: &Substitution<I>, ) -> Binders<FnDefInputsAndOutputDatum<I>>263     fn closure_inputs_and_output(
264         &self,
265         closure_id: ClosureId<I>,
266         substs: &Substitution<I>,
267     ) -> Binders<FnDefInputsAndOutputDatum<I>> {
268         // TODO: record closure IDs
269         self.ws.db().closure_inputs_and_output(closure_id, substs)
270     }
271 
closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>>272     fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> {
273         // TODO: record closure IDs
274         self.ws.db().closure_upvars(closure_id, substs)
275     }
276 
closure_fn_substitution( &self, closure_id: ClosureId<I>, substs: &Substitution<I>, ) -> Substitution<I>277     fn closure_fn_substitution(
278         &self,
279         closure_id: ClosureId<I>,
280         substs: &Substitution<I>,
281     ) -> Substitution<I> {
282         // TODO: record closure IDs
283         self.ws.db().closure_fn_substitution(closure_id, substs)
284     }
285 
discriminant_type(&self, ty: Ty<I>) -> Ty<I>286     fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> {
287         self.ws.db().discriminant_type(ty)
288     }
289 
unification_database(&self) -> &dyn UnificationDatabase<I>290     fn unification_database(&self) -> &dyn UnificationDatabase<I> {
291         self
292     }
293 }
294 
295 /// Wraps a [`RustIrDatabase`], and, when dropped, writes out all used
296 /// definition to the given file.
297 ///
298 /// Uses [`LoggingRustIrDatabase`] internally.
299 ///
300 /// Uses a separate type, `P`, for the database stored inside to account for
301 /// `Arc` or wrapping other storage mediums.
302 pub struct WriteOnDropRustIrDatabase<I, W, DB, P = DB>
303 where
304     I: Interner,
305     W: Write,
306     DB: RustIrDatabase<I>,
307     P: Borrow<DB>,
308 {
309     db: LoggingRustIrDatabase<I, DB, P>,
310     write: W,
311 }
312 
313 impl<I, W, DB, P> fmt::Debug for WriteOnDropRustIrDatabase<I, W, DB, P>
314 where
315     I: Interner,
316     W: Write,
317     DB: RustIrDatabase<I>,
318     P: Borrow<DB> + fmt::Debug,
319 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result320     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321         f.debug_struct("WriteOnDropRustIrDatabase")
322             .field("db", &self.db)
323             .field("write", &"<opaque>")
324             .finish()
325     }
326 }
327 
328 impl<I, W, DB, P> WriteOnDropRustIrDatabase<I, W, DB, P>
329 where
330     I: Interner,
331     W: Write,
332     DB: RustIrDatabase<I>,
333     P: Borrow<DB>,
334 {
new(db: P, write: W) -> Self335     pub fn new(db: P, write: W) -> Self {
336         WriteOnDropRustIrDatabase {
337             db: LoggingRustIrDatabase::new(db),
338             write,
339         }
340     }
341 
from_logging_db(db: LoggingRustIrDatabase<I, DB, P>, write: W) -> Self342     pub fn from_logging_db(db: LoggingRustIrDatabase<I, DB, P>, write: W) -> Self {
343         WriteOnDropRustIrDatabase { db, write }
344     }
345 }
346 
347 impl<I, W, DB, P> Drop for WriteOnDropRustIrDatabase<I, W, DB, P>
348 where
349     I: Interner,
350     W: Write,
351     DB: RustIrDatabase<I>,
352     P: Borrow<DB>,
353 {
drop(&mut self)354     fn drop(&mut self) {
355         write!(self.write, "{}", self.db)
356             .and_then(|_| self.write.flush())
357             .expect("expected to be able to write rust ir database");
358     }
359 }
360 
361 impl<I, W, DB, P> UnificationDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P>
362 where
363     I: Interner,
364     W: Write,
365     DB: RustIrDatabase<I>,
366     P: Borrow<DB> + Debug,
367 {
fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I>368     fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I> {
369         self.db
370             .borrow()
371             .unification_database()
372             .fn_def_variance(fn_def_id)
373     }
374 
adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I>375     fn adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I> {
376         self.db.borrow().unification_database().adt_variance(adt_id)
377     }
378 }
379 
380 impl<I, W, DB, P> RustIrDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P>
381 where
382     I: Interner,
383     W: Write,
384     DB: RustIrDatabase<I>,
385     P: Borrow<DB> + Debug,
386 {
custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>>387     fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
388         self.db.custom_clauses()
389     }
390 
associated_ty_data( &self, ty: chalk_ir::AssocTypeId<I>, ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>>391     fn associated_ty_data(
392         &self,
393         ty: chalk_ir::AssocTypeId<I>,
394     ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> {
395         self.db.associated_ty_data(ty)
396     }
397 
trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>>398     fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> {
399         self.db.trait_datum(trait_id)
400     }
401 
adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>>402     fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> {
403         self.db.adt_datum(adt_id)
404     }
405 
generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>>406     fn generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>> {
407         self.db.borrow().generator_datum(generator_id)
408     }
409 
410     /// Returns the generator witness datum for the generator with the given id.
generator_witness_datum( &self, generator_id: GeneratorId<I>, ) -> Arc<GeneratorWitnessDatum<I>>411     fn generator_witness_datum(
412         &self,
413         generator_id: GeneratorId<I>,
414     ) -> Arc<GeneratorWitnessDatum<I>> {
415         self.db.borrow().generator_witness_datum(generator_id)
416     }
417 
adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>>418     fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>> {
419         self.db.adt_repr(id)
420     }
421 
impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>>422     fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> {
423         self.db.impl_datum(impl_id)
424     }
425 
associated_ty_value( &self, id: crate::rust_ir::AssociatedTyValueId<I>, ) -> Arc<crate::rust_ir::AssociatedTyValue<I>>426     fn associated_ty_value(
427         &self,
428         id: crate::rust_ir::AssociatedTyValueId<I>,
429     ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> {
430         self.db.associated_ty_value(id)
431     }
432 
opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>>433     fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> {
434         self.db.opaque_ty_data(id)
435     }
436 
hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I>437     fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> {
438         self.db.hidden_opaque_type(id)
439     }
440 
impls_for_trait( &self, trait_id: TraitId<I>, parameters: &[chalk_ir::GenericArg<I>], binders: &CanonicalVarKinds<I>, ) -> Vec<ImplId<I>>441     fn impls_for_trait(
442         &self,
443         trait_id: TraitId<I>,
444         parameters: &[chalk_ir::GenericArg<I>],
445         binders: &CanonicalVarKinds<I>,
446     ) -> Vec<ImplId<I>> {
447         self.db.impls_for_trait(trait_id, parameters, binders)
448     }
449 
local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>>450     fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>> {
451         self.db.local_impls_to_coherence_check(trait_id)
452     }
453 
impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool454     fn impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool {
455         self.db.impl_provided_for(auto_trait_id, ty)
456     }
457 
well_known_trait_id( &self, well_known_trait: crate::rust_ir::WellKnownTrait, ) -> Option<TraitId<I>>458     fn well_known_trait_id(
459         &self,
460         well_known_trait: crate::rust_ir::WellKnownTrait,
461     ) -> Option<TraitId<I>> {
462         self.db.well_known_trait_id(well_known_trait)
463     }
464 
program_clauses_for_env( &self, environment: &chalk_ir::Environment<I>, ) -> chalk_ir::ProgramClauses<I>465     fn program_clauses_for_env(
466         &self,
467         environment: &chalk_ir::Environment<I>,
468     ) -> chalk_ir::ProgramClauses<I> {
469         self.db.program_clauses_for_env(environment)
470     }
471 
interner(&self) -> &I472     fn interner(&self) -> &I {
473         self.db.interner()
474     }
475 
is_object_safe(&self, trait_id: TraitId<I>) -> bool476     fn is_object_safe(&self, trait_id: TraitId<I>) -> bool {
477         self.db.is_object_safe(trait_id)
478     }
479 
unification_database(&self) -> &dyn UnificationDatabase<I>480     fn unification_database(&self) -> &dyn UnificationDatabase<I> {
481         self
482     }
483 
trait_name(&self, trait_id: TraitId<I>) -> String484     fn trait_name(&self, trait_id: TraitId<I>) -> String {
485         self.db.trait_name(trait_id)
486     }
487 
adt_name(&self, adt_id: AdtId<I>) -> String488     fn adt_name(&self, adt_id: AdtId<I>) -> String {
489         self.db.adt_name(adt_id)
490     }
491 
assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String492     fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
493         self.db.assoc_type_name(assoc_ty_id)
494     }
495 
opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String496     fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
497         self.db.opaque_type_name(opaque_ty_id)
498     }
499 
fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>>500     fn fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>> {
501         self.db.fn_def_datum(fn_def_id)
502     }
503 
fn_def_name(&self, fn_def_id: FnDefId<I>) -> String504     fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
505         self.db.fn_def_name(fn_def_id)
506     }
507 
closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind508     fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind {
509         // TODO: record closure IDs
510         self.db.closure_kind(closure_id, substs)
511     }
512 
closure_inputs_and_output( &self, closure_id: ClosureId<I>, substs: &Substitution<I>, ) -> Binders<FnDefInputsAndOutputDatum<I>>513     fn closure_inputs_and_output(
514         &self,
515         closure_id: ClosureId<I>,
516         substs: &Substitution<I>,
517     ) -> Binders<FnDefInputsAndOutputDatum<I>> {
518         self.db.closure_inputs_and_output(closure_id, substs)
519     }
520 
closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>>521     fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> {
522         self.db.closure_upvars(closure_id, substs)
523     }
524 
closure_fn_substitution( &self, closure_id: ClosureId<I>, substs: &Substitution<I>, ) -> Substitution<I>525     fn closure_fn_substitution(
526         &self,
527         closure_id: ClosureId<I>,
528         substs: &Substitution<I>,
529     ) -> Substitution<I> {
530         self.db.closure_fn_substitution(closure_id, substs)
531     }
532 
discriminant_type(&self, ty: Ty<I>) -> Ty<I>533     fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> {
534         self.db.discriminant_type(ty)
535     }
536 }
537 
538 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
539 pub enum RecordedItemId<I: Interner> {
540     Adt(AdtId<I>),
541     Trait(TraitId<I>),
542     Impl(ImplId<I>),
543     OpaqueTy(OpaqueTyId<I>),
544     FnDef(FnDefId<I>),
545     Generator(GeneratorId<I>),
546 }
547 
548 impl<I: Interner> From<AdtId<I>> for RecordedItemId<I> {
from(v: AdtId<I>) -> Self549     fn from(v: AdtId<I>) -> Self {
550         RecordedItemId::Adt(v)
551     }
552 }
553 
554 impl<I: Interner> From<TraitId<I>> for RecordedItemId<I> {
from(v: TraitId<I>) -> Self555     fn from(v: TraitId<I>) -> Self {
556         RecordedItemId::Trait(v)
557     }
558 }
559 
560 impl<I: Interner> From<ImplId<I>> for RecordedItemId<I> {
from(v: ImplId<I>) -> Self561     fn from(v: ImplId<I>) -> Self {
562         RecordedItemId::Impl(v)
563     }
564 }
565 
566 impl<I: Interner> From<OpaqueTyId<I>> for RecordedItemId<I> {
from(v: OpaqueTyId<I>) -> Self567     fn from(v: OpaqueTyId<I>) -> Self {
568         RecordedItemId::OpaqueTy(v)
569     }
570 }
571 
572 impl<I: Interner> From<FnDefId<I>> for RecordedItemId<I> {
from(v: FnDefId<I>) -> Self573     fn from(v: FnDefId<I>) -> Self {
574         RecordedItemId::FnDef(v)
575     }
576 }
577 
578 impl<I: Interner> From<GeneratorId<I>> for RecordedItemId<I> {
from(v: GeneratorId<I>) -> Self579     fn from(v: GeneratorId<I>) -> Self {
580         RecordedItemId::Generator(v)
581     }
582 }
583 
584 /// Utility for implementing Ord for RecordedItemId.
585 #[derive(PartialEq, Eq, PartialOrd, Ord)]
586 enum OrderedItemId<'a, DefId, AdtId> {
587     DefId(&'a DefId),
588     AdtId(&'a AdtId),
589 }
590 
591 impl<I: Interner> RecordedItemId<I> {
592     /// Extract internal identifier. Allows for absolute ordering matching the
593     /// order in which chalk saw things (and thus reproducing that order in
594     /// printed programs)
ordered_item_id(&self) -> OrderedItemId<'_, I::DefId, I::InternedAdtId>595     fn ordered_item_id(&self) -> OrderedItemId<'_, I::DefId, I::InternedAdtId> {
596         match self {
597             RecordedItemId::Trait(TraitId(x))
598             | RecordedItemId::Impl(ImplId(x))
599             | RecordedItemId::OpaqueTy(OpaqueTyId(x))
600             | RecordedItemId::Generator(GeneratorId(x))
601             | RecordedItemId::FnDef(FnDefId(x)) => OrderedItemId::DefId(x),
602             RecordedItemId::Adt(AdtId(x)) => OrderedItemId::AdtId(x),
603         }
604     }
605 }
606 
607 impl<I: Interner> PartialOrd for RecordedItemId<I> {
partial_cmp(&self, other: &Self) -> Option<Ordering>608     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
609         Some(self.cmp(other))
610     }
611 }
612 
613 impl<I: Interner> Ord for RecordedItemId<I> {
cmp(&self, other: &Self) -> Ordering614     fn cmp(&self, other: &Self) -> Ordering {
615         self.ordered_item_id().cmp(&other.ordered_item_id())
616     }
617 }
618