1 //! Provides wrappers over `RustIrDatabase` which record used definitions and write
2 //! `.chalk` files containing those definitions.
5 fmt
::{self, Debug, Display}
,
12 use crate::rust_ir
::*;
14 display
::{self, WriterState}
,
17 use chalk_ir
::{interner::Interner, *}
;
19 use indexmap
::IndexSet
;
23 /// Wraps another `RustIrDatabase` (`DB`) and records which definitions are
26 /// A full .chalk file containing all used definitions can be recovered through
27 /// `LoggingRustIrDatabase`'s `Display` implementation.
29 /// Uses a separate type, `P`, for the database stored inside to account for
30 /// `Arc` or wrapping other storage mediums.
32 pub struct LoggingRustIrDatabase
<I
, DB
, P
= DB
>
34 DB
: RustIrDatabase
<I
>,
38 ws
: WriterState
<I
, DB
, P
>,
39 def_ids
: Mutex
<IndexSet
<RecordedItemId
<I
>>>,
40 _phantom
: PhantomData
<DB
>,
43 impl<I
, DB
, P
> LoggingRustIrDatabase
<I
, DB
, P
>
45 DB
: RustIrDatabase
<I
>,
49 pub fn new(db
: P
) -> Self {
50 LoggingRustIrDatabase
{
51 ws
: WriterState
::new(db
),
52 def_ids
: Default
::default(),
53 _phantom
: PhantomData
,
58 impl<I
, DB
, P
> Display
for LoggingRustIrDatabase
<I
, DB
, P
>
60 DB
: RustIrDatabase
<I
>,
64 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())
72 impl<I
, DB
, P
> LoggingRustIrDatabase
<I
, DB
, P
>
74 DB
: RustIrDatabase
<I
>,
78 fn record(&self, id
: impl Into
<RecordedItemId
<I
>>) {
79 self.def_ids
.lock().unwrap().insert(id
.into());
82 fn record_all
<T
, U
>(&self, ids
: T
)
84 T
: IntoIterator
<Item
= U
>,
85 U
: Into
<RecordedItemId
<I
>>,
90 .extend(ids
.into_iter().map(Into
::into
));
94 impl<I
, DB
, P
> UnificationDatabase
<I
> for LoggingRustIrDatabase
<I
, DB
, P
>
96 DB
: RustIrDatabase
<I
>,
97 P
: Borrow
<DB
> + Debug
,
100 fn fn_def_variance(&self, fn_def_id
: chalk_ir
::FnDefId
<I
>) -> Variances
<I
> {
103 .unification_database()
104 .fn_def_variance(fn_def_id
)
107 fn adt_variance(&self, adt_id
: chalk_ir
::AdtId
<I
>) -> Variances
<I
> {
108 self.ws
.db().unification_database().adt_variance(adt_id
)
112 impl<I
, DB
, P
> RustIrDatabase
<I
> for LoggingRustIrDatabase
<I
, DB
, P
>
114 DB
: RustIrDatabase
<I
>,
115 P
: Borrow
<DB
> + Debug
,
118 fn custom_clauses(&self) -> Vec
<chalk_ir
::ProgramClause
<I
>> {
119 self.ws
.db().custom_clauses()
122 fn associated_ty_data(
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
);
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
)
136 fn adt_datum(&self, adt_id
: AdtId
<I
>) -> Arc
<AdtDatum
<I
>> {
138 self.ws
.db().adt_datum(adt_id
)
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
)
146 fn generator_witness_datum(
148 generator_id
: GeneratorId
<I
>,
149 ) -> Arc
<GeneratorWitnessDatum
<I
>> {
150 self.record(generator_id
);
151 self.ws
.db().borrow().generator_witness_datum(generator_id
)
154 fn adt_repr(&self, id
: AdtId
<I
>) -> Arc
<AdtRepr
<I
>> {
156 self.ws
.db().adt_repr(id
)
159 fn adt_size_align(&self, id
: chalk_ir
::AdtId
<I
>) -> Arc
<crate::rust_ir
::AdtSizeAlign
> {
161 self.ws
.db().adt_size_align(id
)
164 fn impl_datum(&self, impl_id
: ImplId
<I
>) -> Arc
<ImplDatum
<I
>> {
165 self.record(impl_id
);
166 self.ws
.db().impl_datum(impl_id
)
169 fn hidden_opaque_type(&self, id
: OpaqueTyId
<I
>) -> Ty
<I
> {
171 self.ws
.db().hidden_opaque_type(id
)
174 fn associated_ty_value(
176 id
: crate::rust_ir
::AssociatedTyValueId
<I
>,
177 ) -> Arc
<crate::rust_ir
::AssociatedTyValue
<I
>> {
178 let value
= self.ws
.db().associated_ty_value(id
);
179 self.record(value
.impl_id
);
183 fn opaque_ty_data(&self, id
: OpaqueTyId
<I
>) -> Arc
<OpaqueTyDatum
<I
>> {
185 self.ws
.db().opaque_ty_data(id
)
190 trait_id
: TraitId
<I
>,
191 parameters
: &[chalk_ir
::GenericArg
<I
>],
192 binders
: &CanonicalVarKinds
<I
>,
193 ) -> Vec
<ImplId
<I
>> {
194 self.record(trait_id
);
195 let impl_ids
= self.ws
.db().impls_for_trait(trait_id
, parameters
, binders
);
196 self.record_all(impl_ids
.iter().copied());
200 fn local_impls_to_coherence_check(&self, trait_id
: TraitId
<I
>) -> Vec
<ImplId
<I
>> {
201 self.record(trait_id
);
202 self.ws
.db().local_impls_to_coherence_check(trait_id
)
205 fn impl_provided_for(&self, auto_trait_id
: TraitId
<I
>, ty
: &TyKind
<I
>) -> bool
{
206 self.record(auto_trait_id
);
207 if let TyKind
::Adt(adt_id
, _
) = ty
{
208 self.record(*adt_id
);
210 self.ws
.db().impl_provided_for(auto_trait_id
, ty
)
213 fn well_known_trait_id(
215 well_known_trait
: crate::rust_ir
::WellKnownTrait
,
216 ) -> Option
<TraitId
<I
>> {
217 let trait_id
= self.ws
.db().well_known_trait_id(well_known_trait
);
218 if let Some(id
) = trait_id
{
224 fn program_clauses_for_env(
226 environment
: &chalk_ir
::Environment
<I
>,
227 ) -> chalk_ir
::ProgramClauses
<I
> {
228 self.ws
.db().program_clauses_for_env(environment
)
231 fn interner(&self) -> I
{
232 self.ws
.db().interner()
235 fn trait_name(&self, trait_id
: TraitId
<I
>) -> String
{
236 self.ws
.db().trait_name(trait_id
)
239 fn adt_name(&self, adt_id
: AdtId
<I
>) -> String
{
240 self.ws
.db().adt_name(adt_id
)
243 fn assoc_type_name(&self, assoc_ty_id
: AssocTypeId
<I
>) -> String
{
244 self.ws
.db().assoc_type_name(assoc_ty_id
)
247 fn opaque_type_name(&self, opaque_ty_id
: OpaqueTyId
<I
>) -> String
{
248 self.ws
.db().opaque_type_name(opaque_ty_id
)
251 fn is_object_safe(&self, trait_id
: TraitId
<I
>) -> bool
{
252 self.record(trait_id
);
253 self.ws
.db().is_object_safe(trait_id
)
256 fn fn_def_datum(&self, fn_def_id
: chalk_ir
::FnDefId
<I
>) -> Arc
<FnDefDatum
<I
>> {
257 self.record(fn_def_id
);
258 self.ws
.db().fn_def_datum(fn_def_id
)
261 fn fn_def_name(&self, fn_def_id
: FnDefId
<I
>) -> String
{
262 self.ws
.db().fn_def_name(fn_def_id
)
265 fn closure_kind(&self, closure_id
: ClosureId
<I
>, substs
: &Substitution
<I
>) -> ClosureKind
{
266 // TODO: record closure IDs
267 self.ws
.db().closure_kind(closure_id
, substs
)
270 fn closure_inputs_and_output(
272 closure_id
: ClosureId
<I
>,
273 substs
: &Substitution
<I
>,
274 ) -> Binders
<FnDefInputsAndOutputDatum
<I
>> {
275 // TODO: record closure IDs
276 self.ws
.db().closure_inputs_and_output(closure_id
, substs
)
279 fn closure_upvars(&self, closure_id
: ClosureId
<I
>, substs
: &Substitution
<I
>) -> Binders
<Ty
<I
>> {
280 // TODO: record closure IDs
281 self.ws
.db().closure_upvars(closure_id
, substs
)
284 fn closure_fn_substitution(
286 closure_id
: ClosureId
<I
>,
287 substs
: &Substitution
<I
>,
288 ) -> Substitution
<I
> {
289 // TODO: record closure IDs
290 self.ws
.db().closure_fn_substitution(closure_id
, substs
)
293 fn discriminant_type(&self, ty
: Ty
<I
>) -> Ty
<I
> {
294 self.ws
.db().discriminant_type(ty
)
297 fn unification_database(&self) -> &dyn UnificationDatabase
<I
> {
302 /// Wraps a [`RustIrDatabase`], and, when dropped, writes out all used
303 /// definition to the given file.
305 /// Uses [`LoggingRustIrDatabase`] internally.
307 /// Uses a separate type, `P`, for the database stored inside to account for
308 /// `Arc` or wrapping other storage mediums.
309 pub struct WriteOnDropRustIrDatabase
<I
, W
, DB
, P
= DB
>
313 DB
: RustIrDatabase
<I
>,
316 db
: LoggingRustIrDatabase
<I
, DB
, P
>,
320 impl<I
, W
, DB
, P
> fmt
::Debug
for WriteOnDropRustIrDatabase
<I
, W
, DB
, P
>
324 DB
: RustIrDatabase
<I
>,
325 P
: Borrow
<DB
> + fmt
::Debug
,
327 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
328 f
.debug_struct("WriteOnDropRustIrDatabase")
329 .field("db", &self.db
)
330 .field("write", &"<opaque>")
335 impl<I
, W
, DB
, P
> WriteOnDropRustIrDatabase
<I
, W
, DB
, P
>
339 DB
: RustIrDatabase
<I
>,
342 pub fn new(db
: P
, write
: W
) -> Self {
343 WriteOnDropRustIrDatabase
{
344 db
: LoggingRustIrDatabase
::new(db
),
349 pub fn from_logging_db(db
: LoggingRustIrDatabase
<I
, DB
, P
>, write
: W
) -> Self {
350 WriteOnDropRustIrDatabase { db, write }
354 impl<I
, W
, DB
, P
> Drop
for WriteOnDropRustIrDatabase
<I
, W
, DB
, P
>
358 DB
: RustIrDatabase
<I
>,
362 write
!(self.write
, "{}", self.db
)
363 .and_then(|_
| self.write
.flush())
364 .expect("expected to be able to write rust ir database");
368 impl<I
, W
, DB
, P
> UnificationDatabase
<I
> for WriteOnDropRustIrDatabase
<I
, W
, DB
, P
>
372 DB
: RustIrDatabase
<I
>,
373 P
: Borrow
<DB
> + Debug
,
375 fn fn_def_variance(&self, fn_def_id
: chalk_ir
::FnDefId
<I
>) -> Variances
<I
> {
378 .unification_database()
379 .fn_def_variance(fn_def_id
)
382 fn adt_variance(&self, adt_id
: chalk_ir
::AdtId
<I
>) -> Variances
<I
> {
383 self.db
.borrow().unification_database().adt_variance(adt_id
)
387 impl<I
, W
, DB
, P
> RustIrDatabase
<I
> for WriteOnDropRustIrDatabase
<I
, W
, DB
, P
>
391 DB
: RustIrDatabase
<I
>,
392 P
: Borrow
<DB
> + Debug
,
394 fn custom_clauses(&self) -> Vec
<chalk_ir
::ProgramClause
<I
>> {
395 self.db
.custom_clauses()
398 fn associated_ty_data(
400 ty
: chalk_ir
::AssocTypeId
<I
>,
401 ) -> Arc
<crate::rust_ir
::AssociatedTyDatum
<I
>> {
402 self.db
.associated_ty_data(ty
)
405 fn trait_datum(&self, trait_id
: TraitId
<I
>) -> Arc
<TraitDatum
<I
>> {
406 self.db
.trait_datum(trait_id
)
409 fn adt_datum(&self, adt_id
: AdtId
<I
>) -> Arc
<AdtDatum
<I
>> {
410 self.db
.adt_datum(adt_id
)
413 fn generator_datum(&self, generator_id
: GeneratorId
<I
>) -> Arc
<GeneratorDatum
<I
>> {
414 self.db
.borrow().generator_datum(generator_id
)
417 /// Returns the generator witness datum for the generator with the given id.
418 fn generator_witness_datum(
420 generator_id
: GeneratorId
<I
>,
421 ) -> Arc
<GeneratorWitnessDatum
<I
>> {
422 self.db
.borrow().generator_witness_datum(generator_id
)
425 fn adt_repr(&self, id
: AdtId
<I
>) -> Arc
<AdtRepr
<I
>> {
429 fn adt_size_align(&self, id
: chalk_ir
::AdtId
<I
>) -> Arc
<crate::rust_ir
::AdtSizeAlign
> {
430 self.db
.adt_size_align(id
)
433 fn impl_datum(&self, impl_id
: ImplId
<I
>) -> Arc
<ImplDatum
<I
>> {
434 self.db
.impl_datum(impl_id
)
437 fn associated_ty_value(
439 id
: crate::rust_ir
::AssociatedTyValueId
<I
>,
440 ) -> Arc
<crate::rust_ir
::AssociatedTyValue
<I
>> {
441 self.db
.associated_ty_value(id
)
444 fn opaque_ty_data(&self, id
: OpaqueTyId
<I
>) -> Arc
<OpaqueTyDatum
<I
>> {
445 self.db
.opaque_ty_data(id
)
448 fn hidden_opaque_type(&self, id
: OpaqueTyId
<I
>) -> Ty
<I
> {
449 self.db
.hidden_opaque_type(id
)
454 trait_id
: TraitId
<I
>,
455 parameters
: &[chalk_ir
::GenericArg
<I
>],
456 binders
: &CanonicalVarKinds
<I
>,
457 ) -> Vec
<ImplId
<I
>> {
458 self.db
.impls_for_trait(trait_id
, parameters
, binders
)
461 fn local_impls_to_coherence_check(&self, trait_id
: TraitId
<I
>) -> Vec
<ImplId
<I
>> {
462 self.db
.local_impls_to_coherence_check(trait_id
)
465 fn impl_provided_for(&self, auto_trait_id
: TraitId
<I
>, ty
: &TyKind
<I
>) -> bool
{
466 self.db
.impl_provided_for(auto_trait_id
, ty
)
469 fn well_known_trait_id(
471 well_known_trait
: crate::rust_ir
::WellKnownTrait
,
472 ) -> Option
<TraitId
<I
>> {
473 self.db
.well_known_trait_id(well_known_trait
)
476 fn program_clauses_for_env(
478 environment
: &chalk_ir
::Environment
<I
>,
479 ) -> chalk_ir
::ProgramClauses
<I
> {
480 self.db
.program_clauses_for_env(environment
)
483 fn interner(&self) -> I
{
487 fn is_object_safe(&self, trait_id
: TraitId
<I
>) -> bool
{
488 self.db
.is_object_safe(trait_id
)
491 fn unification_database(&self) -> &dyn UnificationDatabase
<I
> {
495 fn trait_name(&self, trait_id
: TraitId
<I
>) -> String
{
496 self.db
.trait_name(trait_id
)
499 fn adt_name(&self, adt_id
: AdtId
<I
>) -> String
{
500 self.db
.adt_name(adt_id
)
503 fn assoc_type_name(&self, assoc_ty_id
: AssocTypeId
<I
>) -> String
{
504 self.db
.assoc_type_name(assoc_ty_id
)
507 fn opaque_type_name(&self, opaque_ty_id
: OpaqueTyId
<I
>) -> String
{
508 self.db
.opaque_type_name(opaque_ty_id
)
511 fn fn_def_datum(&self, fn_def_id
: chalk_ir
::FnDefId
<I
>) -> Arc
<FnDefDatum
<I
>> {
512 self.db
.fn_def_datum(fn_def_id
)
515 fn fn_def_name(&self, fn_def_id
: FnDefId
<I
>) -> String
{
516 self.db
.fn_def_name(fn_def_id
)
519 fn closure_kind(&self, closure_id
: ClosureId
<I
>, substs
: &Substitution
<I
>) -> ClosureKind
{
520 // TODO: record closure IDs
521 self.db
.closure_kind(closure_id
, substs
)
524 fn closure_inputs_and_output(
526 closure_id
: ClosureId
<I
>,
527 substs
: &Substitution
<I
>,
528 ) -> Binders
<FnDefInputsAndOutputDatum
<I
>> {
529 self.db
.closure_inputs_and_output(closure_id
, substs
)
532 fn closure_upvars(&self, closure_id
: ClosureId
<I
>, substs
: &Substitution
<I
>) -> Binders
<Ty
<I
>> {
533 self.db
.closure_upvars(closure_id
, substs
)
536 fn closure_fn_substitution(
538 closure_id
: ClosureId
<I
>,
539 substs
: &Substitution
<I
>,
540 ) -> Substitution
<I
> {
541 self.db
.closure_fn_substitution(closure_id
, substs
)
544 fn discriminant_type(&self, ty
: Ty
<I
>) -> Ty
<I
> {
545 self.db
.discriminant_type(ty
)
549 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
550 pub enum RecordedItemId
<I
: Interner
> {
554 OpaqueTy(OpaqueTyId
<I
>),
556 Generator(GeneratorId
<I
>),
559 impl<I
: Interner
> From
<AdtId
<I
>> for RecordedItemId
<I
> {
560 fn from(v
: AdtId
<I
>) -> Self {
561 RecordedItemId
::Adt(v
)
565 impl<I
: Interner
> From
<TraitId
<I
>> for RecordedItemId
<I
> {
566 fn from(v
: TraitId
<I
>) -> Self {
567 RecordedItemId
::Trait(v
)
571 impl<I
: Interner
> From
<ImplId
<I
>> for RecordedItemId
<I
> {
572 fn from(v
: ImplId
<I
>) -> Self {
573 RecordedItemId
::Impl(v
)
577 impl<I
: Interner
> From
<OpaqueTyId
<I
>> for RecordedItemId
<I
> {
578 fn from(v
: OpaqueTyId
<I
>) -> Self {
579 RecordedItemId
::OpaqueTy(v
)
583 impl<I
: Interner
> From
<FnDefId
<I
>> for RecordedItemId
<I
> {
584 fn from(v
: FnDefId
<I
>) -> Self {
585 RecordedItemId
::FnDef(v
)
589 impl<I
: Interner
> From
<GeneratorId
<I
>> for RecordedItemId
<I
> {
590 fn from(v
: GeneratorId
<I
>) -> Self {
591 RecordedItemId
::Generator(v
)