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