]> git.proxmox.com Git - rustc.git/blame - vendor/chalk-solve/src/logging_db.rs
New upstream version 1.47.0~beta.2+dfsg1
[rustc.git] / vendor / chalk-solve / src / logging_db.rs
CommitLineData
3dfed10e
XL
1//! Provides wrappers over `RustIrDatabase` which record used definitions and write
2//! `.chalk` files containing those definitions.
3use 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
14use crate::rust_ir::*;
15use crate::{
16 display::{self, WriterState},
17 RustIrDatabase,
18};
19use chalk_ir::{interner::Interner, *};
20
21mod 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)]
32pub struct LoggingRustIrDatabase<I, DB, P = DB>
33where
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
43impl<I, DB, P> LoggingRustIrDatabase<I, DB, P>
44where
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
58impl<I, DB, P> Display for LoggingRustIrDatabase<I, DB, P>
59where
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
72impl<I, DB, P> LoggingRustIrDatabase<I, DB, P>
73where
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
94impl<I, DB, P> RustIrDatabase<I> for LoggingRustIrDatabase<I, DB, P>
95where
96 DB: RustIrDatabase<I>,
97 P: Borrow<DB> + Debug,
98 I: Interner,
99{
100 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
101 self.ws.db().custom_clauses()
102 }
103
104 fn associated_ty_data(
105 &self,
106 ty: chalk_ir::AssocTypeId<I>,
107 ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> {
108 let ty_datum = self.ws.db().associated_ty_data(ty);
109 self.record(ty_datum.trait_id);
110 ty_datum
111 }
112
113 fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> {
114 self.record(trait_id);
115 self.ws.db().trait_datum(trait_id)
116 }
117
118 fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> {
119 self.record(adt_id);
120 self.ws.db().adt_datum(adt_id)
121 }
122
123 fn adt_repr(&self, id: AdtId<I>) -> AdtRepr {
124 self.record(id);
125 self.ws.db().adt_repr(id)
126 }
127
128 fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> {
129 self.record(impl_id);
130 self.ws.db().impl_datum(impl_id)
131 }
132
133 fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> {
134 self.record(id);
135 self.ws.db().hidden_opaque_type(id)
136 }
137
138 fn associated_ty_value(
139 &self,
140 id: crate::rust_ir::AssociatedTyValueId<I>,
141 ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> {
142 let value = self.ws.db().associated_ty_value(id);
143 self.record(value.impl_id);
144 value
145 }
146
147 fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> {
148 self.record(id);
149 self.ws.db().opaque_ty_data(id)
150 }
151
152 fn impls_for_trait(
153 &self,
154 trait_id: TraitId<I>,
155 parameters: &[chalk_ir::GenericArg<I>],
156 binders: &CanonicalVarKinds<I>,
157 ) -> Vec<ImplId<I>> {
158 self.record(trait_id);
159 let impl_ids = self.ws.db().impls_for_trait(trait_id, parameters, binders);
160 self.record_all(impl_ids.iter().copied());
161 impl_ids
162 }
163
164 fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>> {
165 self.record(trait_id);
166 self.ws.db().local_impls_to_coherence_check(trait_id)
167 }
168
169 fn impl_provided_for(&self, auto_trait_id: TraitId<I>, adt_id: AdtId<I>) -> bool {
170 self.record(auto_trait_id);
171 self.record(adt_id);
172 self.ws.db().impl_provided_for(auto_trait_id, adt_id)
173 }
174
175 fn well_known_trait_id(
176 &self,
177 well_known_trait: crate::rust_ir::WellKnownTrait,
178 ) -> Option<TraitId<I>> {
179 let trait_id = self.ws.db().well_known_trait_id(well_known_trait);
180 trait_id.map(|id| self.record(id));
181 trait_id
182 }
183
184 fn program_clauses_for_env(
185 &self,
186 environment: &chalk_ir::Environment<I>,
187 ) -> chalk_ir::ProgramClauses<I> {
188 self.ws.db().program_clauses_for_env(environment)
189 }
190
191 fn interner(&self) -> &I {
192 self.ws.db().interner()
193 }
194
195 fn trait_name(&self, trait_id: TraitId<I>) -> String {
196 self.ws.db().trait_name(trait_id)
197 }
198
199 fn adt_name(&self, adt_id: AdtId<I>) -> String {
200 self.ws.db().adt_name(adt_id)
201 }
202
203 fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
204 self.ws.db().assoc_type_name(assoc_ty_id)
205 }
206
207 fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
208 self.ws.db().opaque_type_name(opaque_ty_id)
209 }
210
211 fn is_object_safe(&self, trait_id: TraitId<I>) -> bool {
212 self.record(trait_id);
213 self.ws.db().is_object_safe(trait_id)
214 }
215
216 fn fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>> {
217 self.record(fn_def_id);
218 self.ws.db().fn_def_datum(fn_def_id)
219 }
220
221 fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
222 self.ws.db().fn_def_name(fn_def_id)
223 }
224
225 fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind {
226 // TODO: record closure IDs
227 self.ws.db().closure_kind(closure_id, substs)
228 }
229
230 fn closure_inputs_and_output(
231 &self,
232 closure_id: ClosureId<I>,
233 substs: &Substitution<I>,
234 ) -> Binders<FnDefInputsAndOutputDatum<I>> {
235 // TODO: record closure IDs
236 self.ws.db().closure_inputs_and_output(closure_id, substs)
237 }
238
239 fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> {
240 // TODO: record closure IDs
241 self.ws.db().closure_upvars(closure_id, substs)
242 }
243
244 fn closure_fn_substitution(
245 &self,
246 closure_id: ClosureId<I>,
247 substs: &Substitution<I>,
248 ) -> Substitution<I> {
249 // TODO: record closure IDs
250 self.ws.db().closure_fn_substitution(closure_id, substs)
251 }
252}
253
254/// Wraps a [`RustIrDatabase`], and, when dropped, writes out all used
255/// definition to the given file.
256///
257/// Uses [`LoggingRustIrDatabase`] internally.
258///
259/// Uses a separate type, `P`, for the database stored inside to account for
260/// `Arc` or wrapping other storage mediums.
261pub struct WriteOnDropRustIrDatabase<I, W, DB, P = DB>
262where
263 I: Interner,
264 W: Write,
265 DB: RustIrDatabase<I>,
266 P: Borrow<DB>,
267{
268 db: LoggingRustIrDatabase<I, DB, P>,
269 write: W,
270}
271
272impl<I, W, DB, P> fmt::Debug for WriteOnDropRustIrDatabase<I, W, DB, P>
273where
274 I: Interner,
275 W: Write,
276 DB: RustIrDatabase<I>,
277 P: Borrow<DB> + fmt::Debug,
278{
279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280 f.debug_struct("WriteOnDropRustIrDatabase")
281 .field("db", &self.db)
282 .field("write", &"<opaque>")
283 .finish()
284 }
285}
286
287impl<I, W, DB, P> WriteOnDropRustIrDatabase<I, W, DB, P>
288where
289 I: Interner,
290 W: Write,
291 DB: RustIrDatabase<I>,
292 P: Borrow<DB>,
293{
294 pub fn new(db: P, write: W) -> Self {
295 WriteOnDropRustIrDatabase {
296 db: LoggingRustIrDatabase::new(db),
297 write,
298 }
299 }
300
301 pub fn from_logging_db(db: LoggingRustIrDatabase<I, DB, P>, write: W) -> Self {
302 WriteOnDropRustIrDatabase { db, write }
303 }
304}
305
306impl<I, W, DB, P> Drop for WriteOnDropRustIrDatabase<I, W, DB, P>
307where
308 I: Interner,
309 W: Write,
310 DB: RustIrDatabase<I>,
311 P: Borrow<DB>,
312{
313 fn drop(&mut self) {
314 write!(self.write, "{}", self.db)
315 .and_then(|_| self.write.flush())
316 .expect("expected to be able to write rust ir database");
317 }
318}
319
320impl<I, W, DB, P> RustIrDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P>
321where
322 I: Interner,
323 W: Write,
324 DB: RustIrDatabase<I>,
325 P: Borrow<DB> + Debug,
326{
327 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
328 self.db.custom_clauses()
329 }
330
331 fn associated_ty_data(
332 &self,
333 ty: chalk_ir::AssocTypeId<I>,
334 ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> {
335 self.db.associated_ty_data(ty)
336 }
337
338 fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> {
339 self.db.trait_datum(trait_id)
340 }
341
342 fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> {
343 self.db.adt_datum(adt_id)
344 }
345
346 fn adt_repr(&self, id: AdtId<I>) -> AdtRepr {
347 self.db.adt_repr(id)
348 }
349
350 fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> {
351 self.db.impl_datum(impl_id)
352 }
353
354 fn associated_ty_value(
355 &self,
356 id: crate::rust_ir::AssociatedTyValueId<I>,
357 ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> {
358 self.db.associated_ty_value(id)
359 }
360
361 fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> {
362 self.db.opaque_ty_data(id)
363 }
364
365 fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> {
366 self.db.hidden_opaque_type(id)
367 }
368
369 fn impls_for_trait(
370 &self,
371 trait_id: TraitId<I>,
372 parameters: &[chalk_ir::GenericArg<I>],
373 binders: &CanonicalVarKinds<I>,
374 ) -> Vec<ImplId<I>> {
375 self.db.impls_for_trait(trait_id, parameters, binders)
376 }
377
378 fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>> {
379 self.db.local_impls_to_coherence_check(trait_id)
380 }
381
382 fn impl_provided_for(&self, auto_trait_id: TraitId<I>, adt_id: AdtId<I>) -> bool {
383 self.db.impl_provided_for(auto_trait_id, adt_id)
384 }
385
386 fn well_known_trait_id(
387 &self,
388 well_known_trait: crate::rust_ir::WellKnownTrait,
389 ) -> Option<TraitId<I>> {
390 self.db.well_known_trait_id(well_known_trait)
391 }
392
393 fn program_clauses_for_env(
394 &self,
395 environment: &chalk_ir::Environment<I>,
396 ) -> chalk_ir::ProgramClauses<I> {
397 self.db.program_clauses_for_env(environment)
398 }
399
400 fn interner(&self) -> &I {
401 self.db.interner()
402 }
403
404 fn is_object_safe(&self, trait_id: TraitId<I>) -> bool {
405 self.db.is_object_safe(trait_id)
406 }
407
408 fn trait_name(&self, trait_id: TraitId<I>) -> String {
409 self.db.trait_name(trait_id)
410 }
411
412 fn adt_name(&self, adt_id: AdtId<I>) -> String {
413 self.db.adt_name(adt_id)
414 }
415
416 fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
417 self.db.assoc_type_name(assoc_ty_id)
418 }
419
420 fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
421 self.db.opaque_type_name(opaque_ty_id)
422 }
423
424 fn fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>> {
425 self.db.fn_def_datum(fn_def_id)
426 }
427
428 fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
429 self.db.fn_def_name(fn_def_id)
430 }
431
432 fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind {
433 // TODO: record closure IDs
434 self.db.closure_kind(closure_id, substs)
435 }
436
437 fn closure_inputs_and_output(
438 &self,
439 closure_id: ClosureId<I>,
440 substs: &Substitution<I>,
441 ) -> Binders<FnDefInputsAndOutputDatum<I>> {
442 self.db.closure_inputs_and_output(closure_id, substs)
443 }
444
445 fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> {
446 self.db.closure_upvars(closure_id, substs)
447 }
448
449 fn closure_fn_substitution(
450 &self,
451 closure_id: ClosureId<I>,
452 substs: &Substitution<I>,
453 ) -> Substitution<I> {
454 self.db.closure_fn_substitution(closure_id, substs)
455 }
456}
457
458#[derive(Copy, Clone, PartialEq, Eq, Debug)]
459pub enum RecordedItemId<I: Interner> {
460 Adt(AdtId<I>),
461 Trait(TraitId<I>),
462 Impl(ImplId<I>),
463 OpaqueTy(OpaqueTyId<I>),
464 FnDef(FnDefId<I>),
465}
466
467impl<I: Interner> From<AdtId<I>> for RecordedItemId<I> {
468 fn from(v: AdtId<I>) -> Self {
469 RecordedItemId::Adt(v)
470 }
471}
472
473impl<I: Interner> From<TraitId<I>> for RecordedItemId<I> {
474 fn from(v: TraitId<I>) -> Self {
475 RecordedItemId::Trait(v)
476 }
477}
478
479impl<I: Interner> From<ImplId<I>> for RecordedItemId<I> {
480 fn from(v: ImplId<I>) -> Self {
481 RecordedItemId::Impl(v)
482 }
483}
484
485impl<I: Interner> From<OpaqueTyId<I>> for RecordedItemId<I> {
486 fn from(v: OpaqueTyId<I>) -> Self {
487 RecordedItemId::OpaqueTy(v)
488 }
489}
490
491impl<I: Interner> From<FnDefId<I>> for RecordedItemId<I> {
492 fn from(v: FnDefId<I>) -> Self {
493 RecordedItemId::FnDef(v)
494 }
495}
496
497/// Utility for implementing Ord for RecordedItemId.
498#[derive(PartialEq, Eq, PartialOrd, Ord)]
499enum OrderedItemId<'a, DefId, AdtId> {
500 DefId(&'a DefId),
501 AdtId(&'a AdtId),
502}
503
504impl<I: Interner> RecordedItemId<I> {
505 /// Extract internal identifier. Allows for absolute ordering matching the
506 /// order in which chalk saw things (and thus reproducing that order in
507 /// printed programs)
508 fn ordered_item_id(&self) -> OrderedItemId<'_, I::DefId, I::InternedAdtId> {
509 match self {
510 RecordedItemId::Trait(TraitId(x))
511 | RecordedItemId::Impl(ImplId(x))
512 | RecordedItemId::OpaqueTy(OpaqueTyId(x))
513 | RecordedItemId::FnDef(FnDefId(x)) => OrderedItemId::DefId(x),
514 RecordedItemId::Adt(AdtId(x)) => OrderedItemId::AdtId(x),
515 }
516 }
517}
518
519impl<I: Interner> PartialOrd for RecordedItemId<I> {
520 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
521 Some(self.cmp(other))
522 }
523}
524
525impl<I: Interner> Ord for RecordedItemId<I> {
526 fn cmp(&self, other: &Self) -> Ordering {
527 self.ordered_item_id().cmp(&other.ordered_item_id())
528 }
529}