]>
Commit | Line | Data |
---|---|---|
3dfed10e XL |
1 | use std::{ |
2 | borrow::Borrow, | |
3 | fmt::{Display, Result}, | |
4 | sync::Arc, | |
5 | }; | |
6 | ||
7 | use crate::rust_ir::*; | |
8 | use chalk_ir::{interner::Interner, *}; | |
9 | use itertools::Itertools; | |
10 | ||
11 | use crate::{logging_db::RecordedItemId, split::Split, RustIrDatabase}; | |
12 | ||
13 | #[macro_use] | |
14 | mod utils; | |
15 | ||
16 | mod bounds; | |
17 | mod identifiers; | |
18 | mod items; | |
19 | mod render_trait; | |
20 | mod state; | |
21 | mod stub; | |
22 | mod ty; | |
23 | ||
24 | use self::render_trait::*; | |
25 | pub use self::state::*; | |
26 | pub use self::utils::sanitize_debug_name; | |
27 | ||
28 | use self::utils::as_display; | |
29 | ||
30 | fn write_item<F, I, T>(f: &mut F, ws: &InternalWriterState<'_, I>, v: &T) -> Result | |
31 | where | |
32 | F: std::fmt::Write + ?Sized, | |
33 | I: Interner, | |
34 | T: RenderAsRust<I>, | |
35 | { | |
36 | writeln!(f, "{}", v.display(ws)) | |
37 | } | |
38 | ||
39 | /// Writes stubs for items which were referenced by name, but for which we | |
40 | /// didn't directly access. For instance, traits mentioned in where bounds which | |
41 | /// are only usually checked during well-formedness, when we weren't recording | |
42 | /// well-formedness. | |
43 | /// | |
44 | /// The "stub" nature of this means it writes output with the right names and | |
45 | /// the right number of generics, but nothing else. Where clauses, bounds, and | |
46 | /// fields are skipped. Associated types are ???? skipped. | |
47 | /// | |
48 | /// `RecordedItemId::Impl` is not supported. | |
49 | pub fn write_stub_items<F, I, DB, P, T>(f: &mut F, ws: &WriterState<I, DB, P>, ids: T) -> Result | |
50 | where | |
51 | F: std::fmt::Write + ?Sized, | |
52 | I: Interner, | |
53 | DB: RustIrDatabase<I>, | |
54 | P: Borrow<DB>, | |
55 | T: IntoIterator<Item = RecordedItemId<I>>, | |
56 | { | |
57 | let wrapped_db = &ws.wrap_db_ref(|db| stub::StubWrapper::new(db.borrow())); | |
58 | ||
59 | write_items(f, wrapped_db, ids) | |
60 | } | |
61 | ||
62 | /// Writes out each item recorded by a [`LoggingRustIrDatabase`]. | |
63 | /// | |
64 | /// [`LoggingRustIrDatabase`]: crate::logging_db::LoggingRustIrDatabase | |
65 | pub fn write_items<F, I, DB, P, T>(f: &mut F, ws: &WriterState<I, DB, P>, ids: T) -> Result | |
66 | where | |
67 | F: std::fmt::Write + ?Sized, | |
68 | I: Interner, | |
69 | DB: RustIrDatabase<I>, | |
70 | P: Borrow<DB>, | |
71 | T: IntoIterator<Item = RecordedItemId<I>>, | |
72 | { | |
73 | for id in ids { | |
74 | match id { | |
75 | RecordedItemId::Impl(id) => { | |
76 | let v = ws.db().impl_datum(id); | |
77 | write_item(f, &InternalWriterState::new(ws), &*v)?; | |
78 | } | |
79 | RecordedItemId::Adt(id) => { | |
80 | let v = ws.db().adt_datum(id); | |
81 | write_item(f, &InternalWriterState::new(ws), &*v)?; | |
82 | } | |
83 | RecordedItemId::Trait(id) => { | |
84 | let v = ws.db().trait_datum(id); | |
85 | write_item(f, &InternalWriterState::new(ws), &*v)?; | |
86 | } | |
87 | RecordedItemId::OpaqueTy(id) => { | |
88 | let v = ws.db().opaque_ty_data(id); | |
89 | write_item(f, &InternalWriterState::new(ws), &*v)?; | |
90 | } | |
91 | RecordedItemId::FnDef(id) => { | |
92 | let v = ws.db().fn_def_datum(id); | |
93 | write_item(f, &InternalWriterState::new(ws), &*v)?; | |
94 | } | |
29967ef6 XL |
95 | RecordedItemId::Generator(id) => { |
96 | let generator = ws.db().generator_datum(id); | |
97 | let witness = ws.db().generator_witness_datum(id); | |
98 | write_item(f, &InternalWriterState::new(ws), &(&*generator, &*witness))?; | |
99 | } | |
3dfed10e XL |
100 | } |
101 | } | |
102 | Ok(()) | |
103 | } | |
104 | ||
105 | /// Displays a set of bounds, all targeting `Self`, as just the trait names, | |
106 | /// separated by `+`. | |
107 | /// | |
108 | /// For example, a list of quantified where clauses which would normally be | |
109 | /// displayed as: | |
110 | /// | |
111 | /// ```notrust | |
112 | /// Self: A, Self: B, Self: C | |
113 | /// ``` | |
114 | /// | |
115 | /// Is instead displayed by this function as: | |
116 | /// | |
117 | /// ```notrust | |
118 | /// A + B + C | |
119 | /// ``` | |
120 | /// | |
121 | /// Shared between the `Trait` in `dyn Trait` and [`OpaqueTyDatum`] bounds. | |
122 | fn display_self_where_clauses_as_bounds<'a, I: Interner>( | |
123 | s: &'a InternalWriterState<'a, I>, | |
124 | bounds: &'a [QuantifiedWhereClause<I>], | |
125 | ) -> impl Display + 'a { | |
126 | as_display(move |f| { | |
127 | let interner = s.db().interner(); | |
128 | write!( | |
129 | f, | |
130 | "{}", | |
131 | bounds | |
132 | .iter() | |
133 | .map(|bound| { | |
134 | as_display(|f| { | |
135 | // each individual trait can have a forall | |
136 | let s = &s.add_debrujin_index(None); | |
137 | if !bound.binders.is_empty(interner) { | |
138 | write!( | |
139 | f, | |
140 | "forall<{}> ", | |
141 | s.binder_var_display(&bound.binders) | |
142 | .collect::<Vec<_>>() | |
143 | .join(", ") | |
144 | )?; | |
145 | } | |
146 | match &bound.skip_binders() { | |
147 | WhereClause::Implemented(trait_ref) => display_type_with_generics( | |
148 | s, | |
149 | trait_ref.trait_id, | |
150 | &trait_ref.substitution.as_slice(interner)[1..], | |
151 | ) | |
152 | .fmt(f), | |
153 | WhereClause::AliasEq(alias_eq) => match &alias_eq.alias { | |
154 | AliasTy::Projection(projection_ty) => { | |
155 | let (assoc_ty_datum, trait_params, assoc_type_params) = | |
156 | s.db().split_projection(&projection_ty); | |
157 | display_trait_with_assoc_ty_value( | |
158 | s, | |
159 | assoc_ty_datum, | |
160 | &trait_params[1..], | |
161 | assoc_type_params, | |
162 | &alias_eq.ty, | |
163 | ) | |
164 | .fmt(f) | |
165 | } | |
166 | AliasTy::Opaque(_opaque) => todo!("opaque type AliasTy"), | |
167 | }, | |
168 | WhereClause::LifetimeOutlives(lifetime) => lifetime.display(s).fmt(f), | |
169 | WhereClause::TypeOutlives(ty) => ty.display(s).fmt(f), | |
170 | } | |
171 | }) | |
172 | .to_string() | |
173 | }) | |
174 | .format(" + ") | |
175 | ) | |
176 | }) | |
177 | } | |
178 | ||
179 | /// Displays a type with its parameters - something like `AsRef<T>`, | |
180 | /// OpaqueTyName<U>, or `AdtName<Value>`. | |
181 | /// | |
182 | /// This is shared between where bounds, OpaqueTy, & dyn Trait. | |
183 | fn display_type_with_generics<'a, I: Interner>( | |
184 | s: &'a InternalWriterState<'a, I>, | |
185 | trait_name: impl RenderAsRust<I> + 'a, | |
186 | trait_params: impl IntoIterator<Item = &'a GenericArg<I>> + 'a, | |
187 | ) -> impl Display + 'a { | |
188 | use std::fmt::Write; | |
189 | let trait_params = trait_params.into_iter().map(|param| param.display(s)); | |
190 | let mut trait_params_str = String::new(); | |
191 | write_joined_non_empty_list!(trait_params_str, "<{}>", trait_params, ", ").unwrap(); | |
192 | as_display(move |f| write!(f, "{}{}", trait_name.display(s), trait_params_str)) | |
193 | } | |
194 | ||
195 | /// Displays a trait with its parameters and a single associated type - | |
196 | /// something like `IntoIterator<Item=T>`. | |
197 | /// | |
198 | /// This is shared between where bounds & dyn Trait. | |
199 | fn display_trait_with_assoc_ty_value<'a, I: Interner>( | |
200 | s: &'a InternalWriterState<'a, I>, | |
201 | assoc_ty_datum: Arc<AssociatedTyDatum<I>>, | |
202 | trait_params: &'a [GenericArg<I>], | |
203 | assoc_ty_params: &'a [GenericArg<I>], | |
204 | assoc_ty_value: &'a Ty<I>, | |
205 | ) -> impl Display + 'a { | |
206 | as_display(move |f| { | |
207 | write!(f, "{}<", assoc_ty_datum.trait_id.display(s))?; | |
208 | write_joined_non_empty_list!( | |
209 | f, | |
210 | "{}, ", | |
211 | trait_params.iter().map(|param| param.display(s)), | |
212 | ", " | |
213 | )?; | |
214 | write!(f, "{}", assoc_ty_datum.id.display(s))?; | |
215 | write_joined_non_empty_list!( | |
216 | f, | |
217 | "<{}>", | |
218 | assoc_ty_params.iter().map(|param| param.display(s)), | |
219 | ", " | |
220 | )?; | |
221 | write!(f, "={}>", assoc_ty_value.display(s))?; | |
222 | Ok(()) | |
223 | }) | |
224 | } |