Skip to content

.chalk file syntax writer #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 70 commits into from
Jun 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
8cced0f
Initial implementation of the Program Writer
jackh726 Feb 7, 2020
aa91bba
Small cleanup
super-tuple Apr 19, 2020
bcfecd2
Add reparse tests for ProgramWriter
super-tuple Apr 26, 2020
096e10c
Fix associated ty parameter names
super-tuple Apr 26, 2020
ee8f073
Refactor empty env code + tests
super-tuple Apr 26, 2020
0b2fefe
Implement associated ty value rendering in impl
super-tuple Apr 26, 2020
de6924e
Implement RenderAsRust for various ID structs
super-tuple Apr 26, 2020
b92e532
Handle Self, trait polarity & trait attributes
daboross May 3, 2020
075c76f
Clean up extraneous <> and add basic indentation
daboross May 3, 2020
4a0748d
Get recompiling after rebase
super-tuple May 3, 2020
9f45a1e
Get recompiling after rebase
super-tuple May 9, 2020
40f3c3b
Remove WriteProgram in preparation for moving tests
super-tuple May 9, 2020
b889edb
Add RustIrDatabase debug wrappers
super-tuple May 9, 2020
47d3477
Add AssocTyId-specific name retrieval method
super-tuple May 10, 2020
fc7c6a7
Implement scalar types rendering
super-tuple May 10, 2020
8aea128
Fix missing add_debrujin_index cal
super-tuple May 10, 2020
21556f8
Add opaque type definition rendering
super-tuple May 10, 2020
e6410cb
De-duplicated split_associated_ty_parameters
super-tuple May 10, 2020
ae486ad
Add tuple type rendering
super-tuple May 10, 2020
f4a4672
Fix rendered chalk syntax formatting
super-tuple May 10, 2020
56f6378
Move program writing tests into tests crate
super-tuple May 10, 2020
d9ab611
Add reference type rendering
super-tuple May 16, 2020
6e9a020
Add str type rendering
super-tuple May 16, 2020
fcffabd
Add slice type rendering
super-tuple May 16, 2020
e18d343
Add trait impl for built in tests
super-tuple May 16, 2020
2fe84d0
Add impl for generic test
super-tuple May 16, 2020
c6d3de5
Test and fix formatting
super-tuple May 16, 2020
884ebfe
Test and fix assoc where clause formatting
super-tuple May 16, 2020
cd9df5c
Rename logging_db tests directory to display
super-tuple May 16, 2020
10d1009
Implement name disambiguation
super-tuple May 17, 2020
d5b395c
Fix renaming errors from rebase
super-tuple May 23, 2020
62b40fd
Add smart pointer support to LoggingDatabase
super-tuple May 24, 2020
0439683
Add test harness for LoggingRustIrDatabase
super-tuple May 24, 2020
e757cc6
Implement RenderAsRust for Const types
super-tuple May 24, 2020
249d49a
Add logging db tests
super-tuple May 24, 2020
4f87639
Add reparse test macro
super-tuple May 24, 2020
88d244d
Fix unused variable warning
super-tuple May 24, 2020
11ca42f
Refactor display logic into modules
super-tuple May 24, 2020
dec0165
Add linebreaks and fix imports
super-tuple May 24, 2020
485d363
Remove unused dbg!()
super-tuple May 24, 2020
4aeb6f4
Add comment justifying manual reparse goal
super-tuple May 30, 2020
4a349e8
Rename write_program to write_items
super-tuple May 30, 2020
d0ddb6b
Ignore TyKind data
super-tuple May 31, 2020
4083532
Update usage of hidden opaque types
super-tuple May 31, 2020
c54aa5a
Implement RenderAsRust for LifetimeOutlives
super-tuple May 31, 2020
24cb65b
Test and fix const generics
super-tuple May 31, 2020
53f2e51
Add display for array types
super-tuple May 31, 2020
58001df
Clean up tests
super-tuple May 31, 2020
40cfff1
Misc cleanup
super-tuple May 31, 2020
e458772
Implment FnDef rendering
super-tuple May 31, 2020
427b948
Add todo in LoggingDB for closures
super-tuple Jun 21, 2020
63a3955
Add return type rendering for fn types
super-tuple Jun 21, 2020
934445b
Optimize joining iterators with Itertools::format
super-tuple Jun 21, 2020
1858d6a
Add dyn trait lifetime bounds rendering
super-tuple Jun 21, 2020
68210e0
Implement stub items in logging_db
super-tuple Jun 21, 2020
e3cce45
Fix missing names from assoc type bounds
super-tuple Jun 27, 2020
fa55728
Add adt_repr to Logging DB
super-tuple Jun 27, 2020
35fc303
Fix logging db missing assoc ty value names
super-tuple Jun 27, 2020
d9b4e48
Refactor flag macro to error on missing flags
super-tuple Jun 27, 2020
83304fa
Add struct flag rendering
super-tuple Jun 27, 2020
949c75a
Add impl type flag rendering
super-tuple Jun 27, 2020
06d5e4b
Document display sub modules
super-tuple Jun 27, 2020
e656484
Add struct repr rendering
super-tuple Jun 27, 2020
750733f
Implement rendering for well known traits
super-tuple Jun 27, 2020
68263e8
Add object_safe trait flag rendering
super-tuple Jun 27, 2020
a5c160e
Improve LoggingRustIrDatabase tests
super-tuple Jun 27, 2020
024a8a4
Add opaque type Ty rendering
super-tuple Jun 28, 2020
e0f325e
Fix missing opaque ty stubs
super-tuple Jun 28, 2020
20fe0c6
Refactor stub code into RustIrDatabase wrapper
super-tuple Jun 28, 2020
232823b
Implement opaque_ty id collection
super-tuple Jun 28, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@ chalk-integration = { version = "0.16.0-dev.0", path = "chalk-integration" }
[workspace]

[dev-dependencies]
# used for program_writer test errors
diff = "0.1"
pretty_assertions = "0.6.1"
regex = "1"
tracing = "0.1"
20 changes: 20 additions & 0 deletions chalk-integration/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,24 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
.unwrap()
.closure_fn_substitution(closure_id, substs)
}

fn trait_name(&self, trait_id: TraitId<ChalkIr>) -> String {
self.program_ir().unwrap().trait_name(trait_id)
}

fn adt_name(&self, struct_id: AdtId<ChalkIr>) -> String {
self.program_ir().unwrap().adt_name(struct_id)
}

fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<ChalkIr>) -> String {
self.program_ir().unwrap().assoc_type_name(assoc_ty_id)
}

fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<ChalkIr>) -> String {
self.program_ir().unwrap().opaque_type_name(opaque_ty_id)
}

fn fn_def_name(&self, fn_def_id: FnDefId<ChalkIr>) -> String {
self.program_ir().unwrap().fn_def_name(fn_def_id)
}
}
28 changes: 28 additions & 0 deletions chalk-integration/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,4 +468,32 @@ impl RustIrDatabase<ChalkIr> for Program {
) -> Substitution<ChalkIr> {
substs.clone()
}

fn trait_name(&self, trait_id: TraitId<ChalkIr>) -> String {
self.trait_kinds.get(&trait_id).unwrap().name.to_string()
}

fn adt_name(&self, struct_id: AdtId<ChalkIr>) -> String {
self.adt_kinds.get(&struct_id).unwrap().name.to_string()
}

fn assoc_type_name(&self, assoc_type_id: AssocTypeId<ChalkIr>) -> String {
self.associated_ty_data
.get(&assoc_type_id)
.unwrap()
.name
.to_string()
}

fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<ChalkIr>) -> String {
self.opaque_ty_kinds
.get(&opaque_ty_id)
.unwrap()
.name
.to_string()
}

fn fn_def_name(&self, fn_def_id: FnDefId<ChalkIr>) -> String {
self.fn_def_kinds.get(&fn_def_id).unwrap().name.to_string()
}
}
2 changes: 1 addition & 1 deletion chalk-ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ pub enum TyData<I: Interner> {
/// an empty list).
Apply(ApplicationTy<I>),

/// instantiated form a universally quantified type, e.g., from
/// instantiated from a universally quantified type, e.g., from
/// `forall<T> { .. }`. Stands in as a representative of "some
/// unknown type".
Placeholder(PlaceholderIndex),
Expand Down
213 changes: 213 additions & 0 deletions chalk-solve/src/display.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
use std::{
fmt::{Display, Result},
sync::Arc,
};

use crate::rust_ir::*;
use chalk_ir::{interner::Interner, *};
use itertools::Itertools;

use crate::{logging_db::RecordedItemId, split::Split, RustIrDatabase};

#[macro_use]
mod utils;

mod bounds;
mod identifiers;
mod items;
mod render_trait;
mod state;
mod stub;
mod ty;

pub use self::render_trait::*;
pub use self::state::*;

use self::utils::as_display;

pub fn write_item<F, I, T>(f: &mut F, ws: &WriterState<'_, I>, v: &T) -> Result
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably doesn't have to be pub.

where
F: std::fmt::Write + ?Sized,
I: Interner,
T: RenderAsRust<I>,
{
write!(f, "{}\n", v.display(ws))
}

/// Writes stubs for items which were referenced by name, but for which we
/// didn't directly access. For instance, traits mentioned in where bounds which
/// are only usually checked during well-formedness, when we weren't recording
/// well-formedness.
///
/// The "stub" nature of this means it writes output with the right names and
/// the right number of generics, but nothing else. Where clauses, bounds, and
/// fields are skipped. Associated types are ???? skipped.
///
/// `RecordedItemId::Impl` is not supported.
pub fn write_stub_items<F, I, DB, T>(f: &mut F, db: &DB, ids: T) -> Result
where
F: std::fmt::Write + ?Sized,
I: Interner,
DB: RustIrDatabase<I>,
T: IntoIterator<Item = RecordedItemId<I>>,
{
write_items(f, &stub::StubWrapper::new(db), ids)
}

/// Writes out each item recorded by a [`LoggingRustIrDatabase`].
///
/// [`LoggingRustIrDatabase`]: crate::logging_db::LoggingRustIrDatabase
pub fn write_items<F, I, DB, T>(f: &mut F, db: &DB, ids: T) -> Result
where
F: std::fmt::Write + ?Sized,
I: Interner,
DB: RustIrDatabase<I>,
T: IntoIterator<Item = RecordedItemId<I>>,
{
let ws = &WriterState::new(db);
for id in ids {
match id {
RecordedItemId::Impl(id) => {
let v = db.impl_datum(id);
write_item(f, ws, &*v)?;
}
RecordedItemId::Adt(id) => {
let v = db.adt_datum(id);
write_item(f, ws, &*v)?;
}
RecordedItemId::Trait(id) => {
let v = db.trait_datum(id);
write_item(f, ws, &*v)?;
}
RecordedItemId::OpaqueTy(id) => {
let v = db.opaque_ty_data(id);
write_item(f, ws, &*v)?;
}
RecordedItemId::FnDef(id) => {
let v = db.fn_def_datum(id);
write_item(f, ws, &*v)?;
}
}
}
Ok(())
}

/// Displays a set of bounds, all targeting `Self`, as just the trait names,
/// separated by `+`.
///
/// For example, a list of quantified where clauses which would normally be
/// displayed as:
///
/// ```notrust
/// Self: A, Self: B, Self: C
/// ```
///
/// Is instead displayed by this function as:
///
/// ```notrust
/// A + B + C
/// ```
///
/// Shared between the `Trait` in `dyn Trait` and [`OpaqueTyDatum`] bounds.
fn display_self_where_clauses_as_bounds<'a, I: Interner>(
s: &'a WriterState<'a, I>,
bounds: &'a [QuantifiedWhereClause<I>],
) -> impl Display + 'a {
as_display(move |f| {
let interner = s.db.interner();
write!(
f,
"{}",
bounds
.iter()
.map(|bound| {
as_display(|f| {
// each individual trait can have a forall
let s = &s.add_debrujin_index(None);
if !bound.binders.is_empty(interner) {
write!(
f,
"forall<{}> ",
s.binder_var_display(&bound.binders)
.collect::<Vec<_>>()
.join(", ")
)?;
}
match &bound.skip_binders() {
WhereClause::Implemented(trait_ref) => display_type_with_generics(
s,
trait_ref.trait_id,
&trait_ref.substitution.parameters(interner)[1..],
)
.fmt(f),
WhereClause::AliasEq(alias_eq) => match &alias_eq.alias {
AliasTy::Projection(projection_ty) => {
let (assoc_ty_datum, trait_params, assoc_type_params) =
s.db.split_projection(&projection_ty);
display_trait_with_assoc_ty_value(
s,
assoc_ty_datum,
&trait_params[1..],
assoc_type_params,
&alias_eq.ty,
)
.fmt(f)
}
AliasTy::Opaque(_opaque) => todo!("opaque type AliasTy"),
},
WhereClause::LifetimeOutlives(lifetime) => lifetime.display(s).fmt(f),
}
})
.to_string()
})
.format(" + ")
)
})
}

/// Displays a type with its parameters - something like `AsRef<T>`,
/// OpaqueTyName<U>, or `AdtName<Value>`.
///
/// This is shared between where bounds, OpaqueTy, & dyn Trait.
fn display_type_with_generics<'a, I: Interner>(
s: &'a WriterState<'a, I>,
trait_name: impl RenderAsRust<I> + 'a,
trait_params: impl IntoIterator<Item = &'a GenericArg<I>> + 'a,
) -> impl Display + 'a {
use std::fmt::Write;
let trait_params = trait_params.into_iter().map(|param| param.display(s));
let mut trait_params_str = String::new();
write_joined_non_empty_list!(trait_params_str, "<{}>", trait_params, ", ").unwrap();
as_display(move |f| write!(f, "{}{}", trait_name.display(s), trait_params_str))
}

/// Displays a trait with its parameters and a single associated type -
/// something like `IntoIterator<Item=T>`.
///
/// This is shared between where bounds & dyn Trait.
fn display_trait_with_assoc_ty_value<'a, I: Interner>(
s: &'a WriterState<'a, I>,
assoc_ty_datum: Arc<AssociatedTyDatum<I>>,
trait_params: &'a [GenericArg<I>],
assoc_ty_params: &'a [GenericArg<I>],
assoc_ty_value: &'a Ty<I>,
) -> impl Display + 'a {
as_display(move |f| {
write!(f, "{}<", assoc_ty_datum.trait_id.display(s))?;
write_joined_non_empty_list!(
f,
"{}, ",
trait_params.iter().map(|param| param.display(s)),
", "
)?;
write!(f, "{}", assoc_ty_datum.id.display(s))?;
write_joined_non_empty_list!(
f,
"<{}>",
assoc_ty_params.iter().map(|param| param.display(s)),
", "
)?;
write!(f, "={}>", assoc_ty_value.display(s))?;
Ok(())
})
}
Loading