]> git.proxmox.com Git - rustc.git/blob - vendor/chalk-solve/src/logging_db.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / vendor / chalk-solve / src / logging_db.rs
1 //! Provides wrappers over `RustIrDatabase` which record used definitions and write
2 //! `.chalk` files containing those definitions.
3 use std::{
4 borrow::Borrow,
5 fmt::{self, Debug, Display},
6 io::Write,
7 marker::PhantomData,
8 sync::Arc,
9 sync::Mutex,
10 };
11
12 use crate::rust_ir::*;
13 use crate::{
14 display::{self, WriterState},
15 RustIrDatabase,
16 };
17 use chalk_ir::{interner::Interner, *};
18
19 use indexmap::IndexSet;
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<IndexSet<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 {
49 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 {
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())
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 {
78 fn record(&self, id: impl Into<RecordedItemId<I>>) {
79 self.def_ids.lock().unwrap().insert(id.into());
80 }
81
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 {
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
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 {
118 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
119 self.ws.db().custom_clauses()
120 }
121
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
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
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
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
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
154 fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>> {
155 self.record(id);
156 self.ws.db().adt_repr(id)
157 }
158
159 fn adt_size_align(&self, id: chalk_ir::AdtId<I>) -> Arc<crate::rust_ir::AdtSizeAlign> {
160 self.record(id);
161 self.ws.db().adt_size_align(id)
162 }
163
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)
167 }
168
169 fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> {
170 self.record(id);
171 self.ws.db().hidden_opaque_type(id)
172 }
173
174 fn associated_ty_value(
175 &self,
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);
180 value
181 }
182
183 fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> {
184 self.record(id);
185 self.ws.db().opaque_ty_data(id)
186 }
187
188 fn impls_for_trait(
189 &self,
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());
197 impl_ids
198 }
199
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)
203 }
204
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);
209 }
210 self.ws.db().impl_provided_for(auto_trait_id, ty)
211 }
212
213 fn well_known_trait_id(
214 &self,
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 {
219 self.record(id);
220 }
221 trait_id
222 }
223
224 fn program_clauses_for_env(
225 &self,
226 environment: &chalk_ir::Environment<I>,
227 ) -> chalk_ir::ProgramClauses<I> {
228 self.ws.db().program_clauses_for_env(environment)
229 }
230
231 fn interner(&self) -> I {
232 self.ws.db().interner()
233 }
234
235 fn trait_name(&self, trait_id: TraitId<I>) -> String {
236 self.ws.db().trait_name(trait_id)
237 }
238
239 fn adt_name(&self, adt_id: AdtId<I>) -> String {
240 self.ws.db().adt_name(adt_id)
241 }
242
243 fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
244 self.ws.db().assoc_type_name(assoc_ty_id)
245 }
246
247 fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
248 self.ws.db().opaque_type_name(opaque_ty_id)
249 }
250
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)
254 }
255
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)
259 }
260
261 fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
262 self.ws.db().fn_def_name(fn_def_id)
263 }
264
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)
268 }
269
270 fn closure_inputs_and_output(
271 &self,
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)
277 }
278
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)
282 }
283
284 fn closure_fn_substitution(
285 &self,
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)
291 }
292
293 fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> {
294 self.ws.db().discriminant_type(ty)
295 }
296
297 fn unification_database(&self) -> &dyn UnificationDatabase<I> {
298 self
299 }
300 }
301
302 /// Wraps a [`RustIrDatabase`], and, when dropped, writes out all used
303 /// definition to the given file.
304 ///
305 /// Uses [`LoggingRustIrDatabase`] internally.
306 ///
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>
310 where
311 I: Interner,
312 W: Write,
313 DB: RustIrDatabase<I>,
314 P: Borrow<DB>,
315 {
316 db: LoggingRustIrDatabase<I, DB, P>,
317 write: W,
318 }
319
320 impl<I, W, DB, P> fmt::Debug for WriteOnDropRustIrDatabase<I, W, DB, P>
321 where
322 I: Interner,
323 W: Write,
324 DB: RustIrDatabase<I>,
325 P: Borrow<DB> + fmt::Debug,
326 {
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328 f.debug_struct("WriteOnDropRustIrDatabase")
329 .field("db", &self.db)
330 .field("write", &"<opaque>")
331 .finish()
332 }
333 }
334
335 impl<I, W, DB, P> WriteOnDropRustIrDatabase<I, W, DB, P>
336 where
337 I: Interner,
338 W: Write,
339 DB: RustIrDatabase<I>,
340 P: Borrow<DB>,
341 {
342 pub fn new(db: P, write: W) -> Self {
343 WriteOnDropRustIrDatabase {
344 db: LoggingRustIrDatabase::new(db),
345 write,
346 }
347 }
348
349 pub fn from_logging_db(db: LoggingRustIrDatabase<I, DB, P>, write: W) -> Self {
350 WriteOnDropRustIrDatabase { db, write }
351 }
352 }
353
354 impl<I, W, DB, P> Drop for WriteOnDropRustIrDatabase<I, W, DB, P>
355 where
356 I: Interner,
357 W: Write,
358 DB: RustIrDatabase<I>,
359 P: Borrow<DB>,
360 {
361 fn drop(&mut self) {
362 write!(self.write, "{}", self.db)
363 .and_then(|_| self.write.flush())
364 .expect("expected to be able to write rust ir database");
365 }
366 }
367
368 impl<I, W, DB, P> UnificationDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P>
369 where
370 I: Interner,
371 W: Write,
372 DB: RustIrDatabase<I>,
373 P: Borrow<DB> + Debug,
374 {
375 fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I> {
376 self.db
377 .borrow()
378 .unification_database()
379 .fn_def_variance(fn_def_id)
380 }
381
382 fn adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I> {
383 self.db.borrow().unification_database().adt_variance(adt_id)
384 }
385 }
386
387 impl<I, W, DB, P> RustIrDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P>
388 where
389 I: Interner,
390 W: Write,
391 DB: RustIrDatabase<I>,
392 P: Borrow<DB> + Debug,
393 {
394 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
395 self.db.custom_clauses()
396 }
397
398 fn associated_ty_data(
399 &self,
400 ty: chalk_ir::AssocTypeId<I>,
401 ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> {
402 self.db.associated_ty_data(ty)
403 }
404
405 fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> {
406 self.db.trait_datum(trait_id)
407 }
408
409 fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> {
410 self.db.adt_datum(adt_id)
411 }
412
413 fn generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>> {
414 self.db.borrow().generator_datum(generator_id)
415 }
416
417 /// Returns the generator witness datum for the generator with the given id.
418 fn generator_witness_datum(
419 &self,
420 generator_id: GeneratorId<I>,
421 ) -> Arc<GeneratorWitnessDatum<I>> {
422 self.db.borrow().generator_witness_datum(generator_id)
423 }
424
425 fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>> {
426 self.db.adt_repr(id)
427 }
428
429 fn adt_size_align(&self, id: chalk_ir::AdtId<I>) -> Arc<crate::rust_ir::AdtSizeAlign> {
430 self.db.adt_size_align(id)
431 }
432
433 fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> {
434 self.db.impl_datum(impl_id)
435 }
436
437 fn associated_ty_value(
438 &self,
439 id: crate::rust_ir::AssociatedTyValueId<I>,
440 ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> {
441 self.db.associated_ty_value(id)
442 }
443
444 fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> {
445 self.db.opaque_ty_data(id)
446 }
447
448 fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> {
449 self.db.hidden_opaque_type(id)
450 }
451
452 fn impls_for_trait(
453 &self,
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)
459 }
460
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)
463 }
464
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)
467 }
468
469 fn well_known_trait_id(
470 &self,
471 well_known_trait: crate::rust_ir::WellKnownTrait,
472 ) -> Option<TraitId<I>> {
473 self.db.well_known_trait_id(well_known_trait)
474 }
475
476 fn program_clauses_for_env(
477 &self,
478 environment: &chalk_ir::Environment<I>,
479 ) -> chalk_ir::ProgramClauses<I> {
480 self.db.program_clauses_for_env(environment)
481 }
482
483 fn interner(&self) -> I {
484 self.db.interner()
485 }
486
487 fn is_object_safe(&self, trait_id: TraitId<I>) -> bool {
488 self.db.is_object_safe(trait_id)
489 }
490
491 fn unification_database(&self) -> &dyn UnificationDatabase<I> {
492 self
493 }
494
495 fn trait_name(&self, trait_id: TraitId<I>) -> String {
496 self.db.trait_name(trait_id)
497 }
498
499 fn adt_name(&self, adt_id: AdtId<I>) -> String {
500 self.db.adt_name(adt_id)
501 }
502
503 fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
504 self.db.assoc_type_name(assoc_ty_id)
505 }
506
507 fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
508 self.db.opaque_type_name(opaque_ty_id)
509 }
510
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)
513 }
514
515 fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
516 self.db.fn_def_name(fn_def_id)
517 }
518
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)
522 }
523
524 fn closure_inputs_and_output(
525 &self,
526 closure_id: ClosureId<I>,
527 substs: &Substitution<I>,
528 ) -> Binders<FnDefInputsAndOutputDatum<I>> {
529 self.db.closure_inputs_and_output(closure_id, substs)
530 }
531
532 fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> {
533 self.db.closure_upvars(closure_id, substs)
534 }
535
536 fn closure_fn_substitution(
537 &self,
538 closure_id: ClosureId<I>,
539 substs: &Substitution<I>,
540 ) -> Substitution<I> {
541 self.db.closure_fn_substitution(closure_id, substs)
542 }
543
544 fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> {
545 self.db.discriminant_type(ty)
546 }
547 }
548
549 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
550 pub enum RecordedItemId<I: Interner> {
551 Adt(AdtId<I>),
552 Trait(TraitId<I>),
553 Impl(ImplId<I>),
554 OpaqueTy(OpaqueTyId<I>),
555 FnDef(FnDefId<I>),
556 Generator(GeneratorId<I>),
557 }
558
559 impl<I: Interner> From<AdtId<I>> for RecordedItemId<I> {
560 fn from(v: AdtId<I>) -> Self {
561 RecordedItemId::Adt(v)
562 }
563 }
564
565 impl<I: Interner> From<TraitId<I>> for RecordedItemId<I> {
566 fn from(v: TraitId<I>) -> Self {
567 RecordedItemId::Trait(v)
568 }
569 }
570
571 impl<I: Interner> From<ImplId<I>> for RecordedItemId<I> {
572 fn from(v: ImplId<I>) -> Self {
573 RecordedItemId::Impl(v)
574 }
575 }
576
577 impl<I: Interner> From<OpaqueTyId<I>> for RecordedItemId<I> {
578 fn from(v: OpaqueTyId<I>) -> Self {
579 RecordedItemId::OpaqueTy(v)
580 }
581 }
582
583 impl<I: Interner> From<FnDefId<I>> for RecordedItemId<I> {
584 fn from(v: FnDefId<I>) -> Self {
585 RecordedItemId::FnDef(v)
586 }
587 }
588
589 impl<I: Interner> From<GeneratorId<I>> for RecordedItemId<I> {
590 fn from(v: GeneratorId<I>) -> Self {
591 RecordedItemId::Generator(v)
592 }
593 }