diff options
Diffstat (limited to 'vendor/chalk-solve-0.87.0/src/logging_db.rs')
-rw-r--r-- | vendor/chalk-solve-0.87.0/src/logging_db.rs | 593 |
1 files changed, 593 insertions, 0 deletions
diff --git a/vendor/chalk-solve-0.87.0/src/logging_db.rs b/vendor/chalk-solve-0.87.0/src/logging_db.rs new file mode 100644 index 000000000..12d8b052a --- /dev/null +++ b/vendor/chalk-solve-0.87.0/src/logging_db.rs @@ -0,0 +1,593 @@ +//! Provides wrappers over `RustIrDatabase` which record used definitions and write +//! `.chalk` files containing those definitions. +use std::{ + borrow::Borrow, + fmt::{self, Debug, Display}, + io::Write, + marker::PhantomData, + sync::Arc, + sync::Mutex, +}; + +use crate::rust_ir::*; +use crate::{ + display::{self, WriterState}, + RustIrDatabase, +}; +use chalk_ir::{interner::Interner, *}; + +use indexmap::IndexSet; + +mod id_collector; + +/// Wraps another `RustIrDatabase` (`DB`) and records which definitions are +/// used. +/// +/// A full .chalk file containing all used definitions can be recovered through +/// `LoggingRustIrDatabase`'s `Display` implementation. +/// +/// Uses a separate type, `P`, for the database stored inside to account for +/// `Arc` or wrapping other storage mediums. +#[derive(Debug)] +pub struct LoggingRustIrDatabase<I, DB, P = DB> +where + DB: RustIrDatabase<I>, + P: Borrow<DB>, + I: Interner, +{ + ws: WriterState<I, DB, P>, + def_ids: Mutex<IndexSet<RecordedItemId<I>>>, + _phantom: PhantomData<DB>, +} + +impl<I, DB, P> LoggingRustIrDatabase<I, DB, P> +where + DB: RustIrDatabase<I>, + P: Borrow<DB>, + I: Interner, +{ + pub fn new(db: P) -> Self { + LoggingRustIrDatabase { + ws: WriterState::new(db), + def_ids: Default::default(), + _phantom: PhantomData, + } + } +} + +impl<I, DB, P> Display for LoggingRustIrDatabase<I, DB, P> +where + DB: RustIrDatabase<I>, + P: Borrow<DB>, + I: Interner, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let def_ids = self.def_ids.lock().unwrap(); + let stub_ids = id_collector::collect_unrecorded_ids(self.ws.db(), &def_ids); + display::write_stub_items(f, &self.ws, stub_ids)?; + display::write_items(f, &self.ws, def_ids.iter().copied()) + } +} + +impl<I, DB, P> LoggingRustIrDatabase<I, DB, P> +where + DB: RustIrDatabase<I>, + P: Borrow<DB>, + I: Interner, +{ + fn record(&self, id: impl Into<RecordedItemId<I>>) { + self.def_ids.lock().unwrap().insert(id.into()); + } + + fn record_all<T, U>(&self, ids: T) + where + T: IntoIterator<Item = U>, + U: Into<RecordedItemId<I>>, + { + self.def_ids + .lock() + .unwrap() + .extend(ids.into_iter().map(Into::into)); + } +} + +impl<I, DB, P> UnificationDatabase<I> for LoggingRustIrDatabase<I, DB, P> +where + DB: RustIrDatabase<I>, + P: Borrow<DB> + Debug, + I: Interner, +{ + fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I> { + self.ws + .db() + .unification_database() + .fn_def_variance(fn_def_id) + } + + fn adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I> { + self.ws.db().unification_database().adt_variance(adt_id) + } +} + +impl<I, DB, P> RustIrDatabase<I> for LoggingRustIrDatabase<I, DB, P> +where + DB: RustIrDatabase<I>, + P: Borrow<DB> + Debug, + I: Interner, +{ + fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> { + self.ws.db().custom_clauses() + } + + fn associated_ty_data( + &self, + ty: chalk_ir::AssocTypeId<I>, + ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> { + let ty_datum = self.ws.db().associated_ty_data(ty); + self.record(ty_datum.trait_id); + ty_datum + } + + fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> { + self.record(trait_id); + self.ws.db().trait_datum(trait_id) + } + + fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> { + self.record(adt_id); + self.ws.db().adt_datum(adt_id) + } + + fn generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>> { + self.record(generator_id); + self.ws.db().borrow().generator_datum(generator_id) + } + + fn generator_witness_datum( + &self, + generator_id: GeneratorId<I>, + ) -> Arc<GeneratorWitnessDatum<I>> { + self.record(generator_id); + self.ws.db().borrow().generator_witness_datum(generator_id) + } + + fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>> { + self.record(id); + self.ws.db().adt_repr(id) + } + + fn adt_size_align(&self, id: chalk_ir::AdtId<I>) -> Arc<crate::rust_ir::AdtSizeAlign> { + self.record(id); + self.ws.db().adt_size_align(id) + } + + fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> { + self.record(impl_id); + self.ws.db().impl_datum(impl_id) + } + + fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> { + self.record(id); + self.ws.db().hidden_opaque_type(id) + } + + fn associated_ty_value( + &self, + id: crate::rust_ir::AssociatedTyValueId<I>, + ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> { + let value = self.ws.db().associated_ty_value(id); + self.record(value.impl_id); + value + } + + fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> { + self.record(id); + self.ws.db().opaque_ty_data(id) + } + + fn impls_for_trait( + &self, + trait_id: TraitId<I>, + parameters: &[chalk_ir::GenericArg<I>], + binders: &CanonicalVarKinds<I>, + ) -> Vec<ImplId<I>> { + self.record(trait_id); + let impl_ids = self.ws.db().impls_for_trait(trait_id, parameters, binders); + self.record_all(impl_ids.iter().copied()); + impl_ids + } + + fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>> { + self.record(trait_id); + self.ws.db().local_impls_to_coherence_check(trait_id) + } + + fn impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool { + self.record(auto_trait_id); + if let TyKind::Adt(adt_id, _) = ty { + self.record(*adt_id); + } + self.ws.db().impl_provided_for(auto_trait_id, ty) + } + + fn well_known_trait_id( + &self, + well_known_trait: crate::rust_ir::WellKnownTrait, + ) -> Option<TraitId<I>> { + let trait_id = self.ws.db().well_known_trait_id(well_known_trait); + if let Some(id) = trait_id { + self.record(id); + } + trait_id + } + + fn program_clauses_for_env( + &self, + environment: &chalk_ir::Environment<I>, + ) -> chalk_ir::ProgramClauses<I> { + self.ws.db().program_clauses_for_env(environment) + } + + fn interner(&self) -> I { + self.ws.db().interner() + } + + fn trait_name(&self, trait_id: TraitId<I>) -> String { + self.ws.db().trait_name(trait_id) + } + + fn adt_name(&self, adt_id: AdtId<I>) -> String { + self.ws.db().adt_name(adt_id) + } + + fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String { + self.ws.db().assoc_type_name(assoc_ty_id) + } + + fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String { + self.ws.db().opaque_type_name(opaque_ty_id) + } + + fn is_object_safe(&self, trait_id: TraitId<I>) -> bool { + self.record(trait_id); + self.ws.db().is_object_safe(trait_id) + } + + fn fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>> { + self.record(fn_def_id); + self.ws.db().fn_def_datum(fn_def_id) + } + + fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String { + self.ws.db().fn_def_name(fn_def_id) + } + + fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind { + // TODO: record closure IDs + self.ws.db().closure_kind(closure_id, substs) + } + + fn closure_inputs_and_output( + &self, + closure_id: ClosureId<I>, + substs: &Substitution<I>, + ) -> Binders<FnDefInputsAndOutputDatum<I>> { + // TODO: record closure IDs + self.ws.db().closure_inputs_and_output(closure_id, substs) + } + + fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> { + // TODO: record closure IDs + self.ws.db().closure_upvars(closure_id, substs) + } + + fn closure_fn_substitution( + &self, + closure_id: ClosureId<I>, + substs: &Substitution<I>, + ) -> Substitution<I> { + // TODO: record closure IDs + self.ws.db().closure_fn_substitution(closure_id, substs) + } + + fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> { + self.ws.db().discriminant_type(ty) + } + + fn unification_database(&self) -> &dyn UnificationDatabase<I> { + self + } +} + +/// Wraps a [`RustIrDatabase`], and, when dropped, writes out all used +/// definition to the given file. +/// +/// Uses [`LoggingRustIrDatabase`] internally. +/// +/// Uses a separate type, `P`, for the database stored inside to account for +/// `Arc` or wrapping other storage mediums. +pub struct WriteOnDropRustIrDatabase<I, W, DB, P = DB> +where + I: Interner, + W: Write, + DB: RustIrDatabase<I>, + P: Borrow<DB>, +{ + db: LoggingRustIrDatabase<I, DB, P>, + write: W, +} + +impl<I, W, DB, P> fmt::Debug for WriteOnDropRustIrDatabase<I, W, DB, P> +where + I: Interner, + W: Write, + DB: RustIrDatabase<I>, + P: Borrow<DB> + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WriteOnDropRustIrDatabase") + .field("db", &self.db) + .field("write", &"<opaque>") + .finish() + } +} + +impl<I, W, DB, P> WriteOnDropRustIrDatabase<I, W, DB, P> +where + I: Interner, + W: Write, + DB: RustIrDatabase<I>, + P: Borrow<DB>, +{ + pub fn new(db: P, write: W) -> Self { + WriteOnDropRustIrDatabase { + db: LoggingRustIrDatabase::new(db), + write, + } + } + + pub fn from_logging_db(db: LoggingRustIrDatabase<I, DB, P>, write: W) -> Self { + WriteOnDropRustIrDatabase { db, write } + } +} + +impl<I, W, DB, P> Drop for WriteOnDropRustIrDatabase<I, W, DB, P> +where + I: Interner, + W: Write, + DB: RustIrDatabase<I>, + P: Borrow<DB>, +{ + fn drop(&mut self) { + write!(self.write, "{}", self.db) + .and_then(|_| self.write.flush()) + .expect("expected to be able to write rust ir database"); + } +} + +impl<I, W, DB, P> UnificationDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P> +where + I: Interner, + W: Write, + DB: RustIrDatabase<I>, + P: Borrow<DB> + Debug, +{ + fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I> { + self.db + .borrow() + .unification_database() + .fn_def_variance(fn_def_id) + } + + fn adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I> { + self.db.borrow().unification_database().adt_variance(adt_id) + } +} + +impl<I, W, DB, P> RustIrDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P> +where + I: Interner, + W: Write, + DB: RustIrDatabase<I>, + P: Borrow<DB> + Debug, +{ + fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> { + self.db.custom_clauses() + } + + fn associated_ty_data( + &self, + ty: chalk_ir::AssocTypeId<I>, + ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> { + self.db.associated_ty_data(ty) + } + + fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> { + self.db.trait_datum(trait_id) + } + + fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> { + self.db.adt_datum(adt_id) + } + + fn generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>> { + self.db.borrow().generator_datum(generator_id) + } + + /// Returns the generator witness datum for the generator with the given id. + fn generator_witness_datum( + &self, + generator_id: GeneratorId<I>, + ) -> Arc<GeneratorWitnessDatum<I>> { + self.db.borrow().generator_witness_datum(generator_id) + } + + fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>> { + self.db.adt_repr(id) + } + + fn adt_size_align(&self, id: chalk_ir::AdtId<I>) -> Arc<crate::rust_ir::AdtSizeAlign> { + self.db.adt_size_align(id) + } + + fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> { + self.db.impl_datum(impl_id) + } + + fn associated_ty_value( + &self, + id: crate::rust_ir::AssociatedTyValueId<I>, + ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> { + self.db.associated_ty_value(id) + } + + fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> { + self.db.opaque_ty_data(id) + } + + fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> { + self.db.hidden_opaque_type(id) + } + + fn impls_for_trait( + &self, + trait_id: TraitId<I>, + parameters: &[chalk_ir::GenericArg<I>], + binders: &CanonicalVarKinds<I>, + ) -> Vec<ImplId<I>> { + self.db.impls_for_trait(trait_id, parameters, binders) + } + + fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>> { + self.db.local_impls_to_coherence_check(trait_id) + } + + fn impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool { + self.db.impl_provided_for(auto_trait_id, ty) + } + + fn well_known_trait_id( + &self, + well_known_trait: crate::rust_ir::WellKnownTrait, + ) -> Option<TraitId<I>> { + self.db.well_known_trait_id(well_known_trait) + } + + fn program_clauses_for_env( + &self, + environment: &chalk_ir::Environment<I>, + ) -> chalk_ir::ProgramClauses<I> { + self.db.program_clauses_for_env(environment) + } + + fn interner(&self) -> I { + self.db.interner() + } + + fn is_object_safe(&self, trait_id: TraitId<I>) -> bool { + self.db.is_object_safe(trait_id) + } + + fn unification_database(&self) -> &dyn UnificationDatabase<I> { + self + } + + fn trait_name(&self, trait_id: TraitId<I>) -> String { + self.db.trait_name(trait_id) + } + + fn adt_name(&self, adt_id: AdtId<I>) -> String { + self.db.adt_name(adt_id) + } + + fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String { + self.db.assoc_type_name(assoc_ty_id) + } + + fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String { + self.db.opaque_type_name(opaque_ty_id) + } + + fn fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>> { + self.db.fn_def_datum(fn_def_id) + } + + fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String { + self.db.fn_def_name(fn_def_id) + } + + fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind { + // TODO: record closure IDs + self.db.closure_kind(closure_id, substs) + } + + fn closure_inputs_and_output( + &self, + closure_id: ClosureId<I>, + substs: &Substitution<I>, + ) -> Binders<FnDefInputsAndOutputDatum<I>> { + self.db.closure_inputs_and_output(closure_id, substs) + } + + fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> { + self.db.closure_upvars(closure_id, substs) + } + + fn closure_fn_substitution( + &self, + closure_id: ClosureId<I>, + substs: &Substitution<I>, + ) -> Substitution<I> { + self.db.closure_fn_substitution(closure_id, substs) + } + + fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> { + self.db.discriminant_type(ty) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +pub enum RecordedItemId<I: Interner> { + Adt(AdtId<I>), + Trait(TraitId<I>), + Impl(ImplId<I>), + OpaqueTy(OpaqueTyId<I>), + FnDef(FnDefId<I>), + Generator(GeneratorId<I>), +} + +impl<I: Interner> From<AdtId<I>> for RecordedItemId<I> { + fn from(v: AdtId<I>) -> Self { + RecordedItemId::Adt(v) + } +} + +impl<I: Interner> From<TraitId<I>> for RecordedItemId<I> { + fn from(v: TraitId<I>) -> Self { + RecordedItemId::Trait(v) + } +} + +impl<I: Interner> From<ImplId<I>> for RecordedItemId<I> { + fn from(v: ImplId<I>) -> Self { + RecordedItemId::Impl(v) + } +} + +impl<I: Interner> From<OpaqueTyId<I>> for RecordedItemId<I> { + fn from(v: OpaqueTyId<I>) -> Self { + RecordedItemId::OpaqueTy(v) + } +} + +impl<I: Interner> From<FnDefId<I>> for RecordedItemId<I> { + fn from(v: FnDefId<I>) -> Self { + RecordedItemId::FnDef(v) + } +} + +impl<I: Interner> From<GeneratorId<I>> for RecordedItemId<I> { + fn from(v: GeneratorId<I>) -> Self { + RecordedItemId::Generator(v) + } +} |