]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | //! Writer logic for top level items. |
2 | //! | |
3 | //! Contains code specific to top-level items and other structures specific to a | |
4 | //! single top-level item. | |
5 | ||
6 | use std::fmt::{Formatter, Result}; | |
7 | ||
8 | use crate::rust_ir::*; | |
9 | use crate::split::Split; | |
10 | use chalk_ir::interner::Interner; | |
11 | use itertools::Itertools; | |
12 | ||
13 | use super::{ | |
14 | display_self_where_clauses_as_bounds, display_type_with_generics, render_trait::RenderAsRust, | |
15 | state::InternalWriterState, | |
16 | }; | |
17 | ||
18 | /// Used in `AdtDatum` and `TraitDatum` to write n flags from a flags struct | |
19 | /// to a writer. Each flag field turns into an if expression + write!, so we can | |
20 | /// just list the names and not repeat this pattern over and over. | |
21 | /// | |
22 | /// This macro will error if unknown flags are specified. This will also error | |
23 | /// if any flags are missing. | |
24 | /// | |
25 | /// # Usage | |
26 | /// | |
27 | /// ```rust,ignore | |
28 | /// write_flags!(f, self.flags, XFlags { red, green }) | |
29 | /// ``` | |
30 | /// | |
31 | /// Turns into | |
32 | /// | |
33 | /// ```rust,ignore | |
34 | /// match self.flags { | |
35 | /// XFlags { red, green } => { | |
36 | /// if red { | |
37 | /// write!(f, "#[red]")?; | |
38 | /// } | |
39 | /// if green { | |
40 | /// write!(f, "#[green]")?; | |
41 | /// } | |
42 | /// } | |
43 | /// } | |
44 | /// ``` | |
45 | macro_rules! write_flags { | |
46 | ($writer:ident, $val:expr, $struct_name:ident { $($n:ident $(: $extra_arg:tt)?),* }) => { | |
47 | match $val { | |
48 | // if any fields are missing, the destructuring will error | |
49 | $struct_name { | |
50 | $($n,)* | |
51 | } => { | |
52 | $(if $n { | |
53 | write!($writer, "#[{}]\n", write_flags!(@default $n $(: $extra_arg)*))?; | |
54 | })* | |
55 | } | |
56 | } | |
57 | }; | |
58 | (@default $n:ident : $name:literal) => { | |
59 | $name | |
60 | }; | |
61 | (@default $n:ident ) => { | |
62 | stringify!($n) | |
63 | }; | |
64 | } | |
65 | ||
66 | impl<I: Interner> RenderAsRust<I> for AdtDatum<I> { | |
67 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
68 | // When support for Self in structs is added, self_binding should be | |
69 | // changed to Some(0) | |
70 | let s = &s.add_debrujin_index(None); | |
71 | let value = self.binders.skip_binders(); | |
72 | ||
73 | // flags | |
74 | write_flags!( | |
75 | f, | |
76 | self.flags, | |
77 | AdtFlags { | |
78 | // Ordering matters | |
79 | upstream, | |
80 | fundamental, | |
81 | phantom_data | |
82 | } | |
83 | ); | |
84 | ||
85 | // repr | |
86 | let repr = s.db().adt_repr(self.id); | |
87 | ||
88 | write_flags!( | |
89 | f, | |
90 | repr, | |
91 | AdtRepr { | |
92 | repr_c: "repr(C)", | |
93 | repr_packed: "repr(packed)" | |
94 | } | |
95 | ); | |
96 | ||
97 | // name | |
98 | match self.kind { | |
99 | AdtKind::Struct => write!(f, "struct {}", self.id.display(s),)?, | |
100 | AdtKind::Enum => write!(f, "enum {}", self.id.display(s),)?, | |
101 | AdtKind::Union => write!(f, "union {}", self.id.display(s),)?, | |
102 | } | |
103 | write_joined_non_empty_list!(f, "<{}>", s.binder_var_display(&self.binders.binders), ", ")?; | |
104 | ||
105 | // where clauses | |
106 | if !value.where_clauses.is_empty() { | |
107 | let s = &s.add_indent(); | |
108 | write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?; | |
109 | } else { | |
110 | write!(f, " ")?; | |
111 | } | |
112 | ||
113 | // body | |
114 | write!(f, "{{")?; | |
115 | let s = &s.add_indent(); | |
116 | match self.kind { | |
117 | AdtKind::Struct | AdtKind::Union => { | |
118 | write_joined_non_empty_list!( | |
119 | f, | |
120 | "\n{}\n", | |
121 | value.variants[0] | |
122 | .fields | |
123 | .iter() | |
124 | .enumerate() | |
125 | .map(|(idx, field)| { | |
126 | format!("{}field_{}: {}", s.indent(), idx, field.display(s)) | |
127 | }), | |
128 | ",\n" | |
129 | )?; | |
130 | } | |
131 | AdtKind::Enum => { | |
132 | for (variant_idx, variant) in value.variants.iter().enumerate() { | |
133 | write!(f, "\n{}variant_{} {{", s.indent(), variant_idx)?; | |
134 | let s = &s.add_indent(); | |
135 | write_joined_non_empty_list!( | |
136 | f, | |
137 | "\n{}\n", | |
138 | variant.fields.iter().enumerate().map(|(idx, field)| { | |
139 | format!("{}field_{}: {}", s.indent(), idx, field.display(s)) | |
140 | }), | |
141 | ",\n" | |
142 | )?; | |
143 | write!(f, "{}}},", s.indent())?; | |
144 | } | |
145 | } | |
146 | } | |
147 | write!(f, "}}")?; | |
148 | Ok(()) | |
149 | } | |
150 | } | |
151 | ||
152 | impl<I: Interner> RenderAsRust<I> for Polarity { | |
153 | fn fmt(&self, _s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
154 | if !self.is_positive() { | |
155 | write!(f, "!")?; | |
156 | } | |
157 | Ok(()) | |
158 | } | |
159 | } | |
160 | ||
161 | impl<I: Interner> RenderAsRust<I> for TraitDatum<I> { | |
162 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
163 | let s = &s.add_debrujin_index(Some(0)); | |
164 | let value = self.binders.skip_binders(); | |
165 | ||
166 | // flags | |
167 | write_flags!( | |
168 | f, | |
169 | self.flags, | |
170 | TraitFlags { | |
171 | auto, | |
172 | marker, | |
173 | upstream, | |
174 | fundamental, | |
175 | non_enumerable, | |
176 | coinductive | |
177 | } | |
178 | ); | |
179 | ||
180 | // object safe | |
181 | if s.db().is_object_safe(self.id) { | |
182 | writeln!(f, "#[object_safe]")?; | |
183 | } | |
184 | ||
185 | // well-known | |
186 | if let Some(well_known) = self.well_known { | |
187 | let name = match well_known { | |
188 | WellKnownTrait::Sized => "sized", | |
189 | WellKnownTrait::Copy => "copy", | |
190 | WellKnownTrait::Clone => "clone", | |
191 | WellKnownTrait::Drop => "drop", | |
192 | WellKnownTrait::FnOnce => "fn_once", | |
193 | WellKnownTrait::FnMut => "fn_mut", | |
194 | WellKnownTrait::Fn => "fn", | |
195 | WellKnownTrait::Unsize => "unsize", | |
196 | }; | |
197 | writeln!(f, "#[lang({})]", name)?; | |
198 | } | |
199 | ||
200 | // trait declaration | |
201 | let binders = s.binder_var_display(&self.binders.binders).skip(1); | |
202 | write!(f, "trait {}", self.id.display(s))?; | |
203 | write_joined_non_empty_list!(f, "<{}>", binders, ", ")?; | |
204 | ||
205 | // where clauses | |
206 | if !value.where_clauses.is_empty() { | |
207 | let s = &s.add_indent(); | |
208 | write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?; | |
209 | } else { | |
210 | write!(f, " ")?; | |
211 | } | |
212 | ||
213 | // body | |
214 | write!(f, "{{")?; | |
215 | let s = &s.add_indent(); | |
216 | write_joined_non_empty_list!( | |
217 | f, | |
218 | "\n{}\n", | |
219 | self.associated_ty_ids.iter().map(|assoc_ty_id| { | |
220 | let assoc_ty_data = s.db().associated_ty_data(*assoc_ty_id); | |
221 | format!("{}{}", s.indent(), (*assoc_ty_data).display(s)) | |
222 | }), | |
223 | "\n" | |
224 | )?; | |
225 | write!(f, "}}")?; | |
226 | Ok(()) | |
227 | } | |
228 | } | |
229 | ||
230 | impl<I: Interner> RenderAsRust<I> for ImplDatum<I> { | |
231 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
232 | let interner = s.db().interner(); | |
233 | ||
234 | let s = &s.add_debrujin_index(None); | |
235 | let binders = s.binder_var_display(&self.binders.binders); | |
236 | let value = self.binders.skip_binders(); | |
237 | ||
238 | // annotations | |
239 | // #[upstream] | |
240 | // ^^^^^^^^^^^ | |
241 | // impl<T> Foo<T> for Bar<T> where T: Baz { } | |
242 | if self.impl_type == ImplType::External { | |
243 | writeln!(f, "#[upstream]")?; | |
244 | } | |
245 | ||
246 | // impl keyword | |
247 | // impl<T> Foo<T> for Bar<T> where T: Baz { } | |
248 | // ^^^^ | |
249 | write!(f, "impl")?; | |
250 | let trait_ref = &value.trait_ref; | |
251 | ||
252 | // generic binders | |
253 | // impl<T> Foo<T> for Bar<T> where T: Baz | |
254 | // ^^^ | |
255 | write_joined_non_empty_list!(f, "<{}>", binders, ", ")?; | |
256 | ||
257 | // trait, type and parameters | |
258 | // impl<T> Foo<T> for Bar<T> where T: Baz { } | |
259 | // ^^^^^^^^^^^^^^^^^ | |
260 | let full_trait_name = display_type_with_generics( | |
261 | s, | |
262 | trait_ref.trait_id, | |
263 | // Ignore automatically added Self parameter by skipping first parameter | |
264 | &trait_ref.substitution.as_slice(interner)[1..], | |
265 | ); | |
266 | write!( | |
267 | f, | |
268 | " {}{} for {}", | |
269 | self.polarity.display(s), | |
270 | full_trait_name, | |
271 | trait_ref.self_type_parameter(interner).display(s) | |
272 | )?; | |
273 | ||
274 | // where clauses | |
275 | // impl<T> Foo<T> for Bar<T> where T: Baz { } | |
276 | // ^^^^^^^^^^^^ | |
277 | if !value.where_clauses.is_empty() { | |
278 | let s = &s.add_indent(); | |
279 | write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?; | |
280 | } else { | |
281 | write!(f, " ")?; | |
282 | } | |
283 | ||
284 | // body | |
285 | // impl<T> Foo<T> for Bar<T> where T: Baz { } | |
286 | // ^^^ | |
287 | write!(f, "{{")?; | |
288 | { | |
289 | let s = &s.add_indent(); | |
290 | let assoc_ty_values = self.associated_ty_value_ids.iter().map(|assoc_ty_value| { | |
291 | s.db() | |
292 | .associated_ty_value(*assoc_ty_value) | |
293 | .display(s) | |
294 | .to_string() | |
295 | }); | |
296 | write_joined_non_empty_list!(f, "\n{}\n", assoc_ty_values, "\n")?; | |
297 | } | |
298 | write!(f, "}}")?; | |
299 | Ok(()) | |
300 | } | |
301 | } | |
302 | ||
303 | impl<I: Interner> RenderAsRust<I> for OpaqueTyDatum<I> { | |
304 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { | |
305 | let s = &s.add_debrujin_index(None); | |
306 | let bounds = self.bound.skip_binders(); | |
307 | write!(f, "opaque type {}", self.opaque_ty_id.display(s))?; | |
308 | write_joined_non_empty_list!(f, "<{}>", s.binder_var_display(&self.bound.binders), ", ")?; | |
309 | { | |
310 | let s = &s.add_debrujin_index(Some(0)); | |
311 | let clauses = bounds.bounds.skip_binders(); | |
312 | write!( | |
313 | f, | |
314 | ": {} = ", | |
315 | display_self_where_clauses_as_bounds(s, clauses) | |
316 | )?; | |
317 | } | |
318 | write!( | |
319 | f, | |
320 | "{};", | |
321 | s.db().hidden_opaque_type(self.opaque_ty_id).display(s) | |
322 | )?; | |
323 | Ok(()) | |
324 | } | |
325 | } | |
326 | ||
327 | impl<I: Interner> RenderAsRust<I> for AssociatedTyDatum<I> { | |
328 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
329 | // In lowering, a completely new empty environment is created for each | |
330 | // AssociatedTyDatum, and it's given generic parameters for each generic | |
331 | // parameter that its trait had. We want to map the new binders for | |
332 | // those generic parameters back into their original names. To do that, | |
333 | // first find their original names (trait_binder_names), then the names | |
334 | // they have inside the AssociatedTyDatum (assoc_ty_names_for_trait_params), | |
335 | // and then add that mapping to the WriterState when writing bounds and | |
336 | // where clauses. | |
337 | let trait_datum = s.db().trait_datum(self.trait_id); | |
338 | // inverted Debrujin indices for the trait's parameters in the trait | |
339 | // environment | |
340 | let trait_param_names_in_trait_env = s.binder_var_indices(&trait_datum.binders.binders); | |
341 | let s = &s.add_debrujin_index(None); | |
342 | // inverted Debrujin indices for the trait's parameters in the | |
343 | // associated type environment | |
344 | let param_names_in_assoc_ty_env = s | |
345 | .binder_var_indices(&self.binders.binders) | |
346 | .collect::<Vec<_>>(); | |
347 | // inverted Debrujin indices to render the trait's parameters in the | |
348 | // associated type environment | |
349 | let (trait_param_names_in_assoc_ty_env, _) = s | |
350 | .db() | |
351 | .split_associated_ty_parameters(¶m_names_in_assoc_ty_env, self); | |
352 | ||
353 | let s = &s.add_parameter_mapping( | |
354 | trait_param_names_in_assoc_ty_env.iter().copied(), | |
355 | trait_param_names_in_trait_env, | |
356 | ); | |
357 | ||
358 | // rendered names for the associated type's generics in the associated | |
359 | // type environment | |
360 | let binder_display_in_assoc_ty = s | |
361 | .binder_var_display(&self.binders.binders) | |
362 | .collect::<Vec<_>>(); | |
363 | ||
364 | let (_, assoc_ty_params) = s | |
365 | .db() | |
366 | .split_associated_ty_parameters(&binder_display_in_assoc_ty, self); | |
367 | write!(f, "type {}", self.id.display(s))?; | |
368 | write_joined_non_empty_list!(f, "<{}>", assoc_ty_params, ", ")?; | |
369 | ||
370 | let datum_bounds = &self.binders.skip_binders(); | |
371 | ||
372 | if !datum_bounds.bounds.is_empty() { | |
373 | write!(f, ": ")?; | |
374 | } | |
375 | ||
376 | // bounds is `A: V, B: D, C = E`? | |
377 | // type Foo<A: V, B:D, C = E>: X + Y + Z; | |
378 | let bounds = datum_bounds | |
379 | .bounds | |
380 | .iter() | |
381 | .map(|bound| bound.display(s).to_string()) | |
382 | .format(" + "); | |
383 | write!(f, "{}", bounds)?; | |
384 | ||
385 | // where_clause is 'X: Y, Z: D' | |
386 | // type Foo<...>: ... where X: Y, Z: D; | |
387 | ||
388 | // note: it's a quantified clause b/c we could have `for<'a> T: Foo<'a>` | |
389 | // within 'where' | |
390 | if !datum_bounds.where_clauses.is_empty() { | |
391 | let where_s = &s.add_indent(); | |
392 | let where_clauses = datum_bounds.where_clauses.display(where_s); | |
393 | write!(f, "\n{}where\n{}", s.indent(), where_clauses)?; | |
394 | } | |
395 | write!(f, ";")?; | |
396 | Ok(()) | |
397 | } | |
398 | } | |
399 | ||
400 | impl<I: Interner> RenderAsRust<I> for AssociatedTyValue<I> { | |
401 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
402 | // see comments for a similar empty env operation in AssociatedTyDatum's | |
403 | // impl of RenderAsRust. | |
404 | let assoc_ty_data = s.db().associated_ty_data(self.associated_ty_id); | |
405 | let impl_datum = s.db().impl_datum(self.impl_id); | |
406 | ||
407 | let impl_param_names_in_impl_env = s.binder_var_indices(&impl_datum.binders.binders); | |
408 | ||
409 | let s = &s.add_debrujin_index(None); | |
410 | let value = self.value.skip_binders(); | |
411 | ||
412 | let param_names_in_assoc_ty_value_env = s | |
413 | .binder_var_indices(&self.value.binders) | |
414 | .collect::<Vec<_>>(); | |
415 | ||
416 | let (impl_params_in_assoc_ty_value_env, _assoc_ty_value_params) = s | |
417 | .db() | |
418 | .split_associated_ty_value_parameters(¶m_names_in_assoc_ty_value_env, self); | |
419 | ||
420 | let s = &s.add_parameter_mapping( | |
421 | impl_params_in_assoc_ty_value_env.iter().cloned(), | |
422 | impl_param_names_in_impl_env, | |
423 | ); | |
424 | ||
425 | let display_params = s | |
426 | .binder_var_display(&self.value.binders) | |
427 | .collect::<Vec<_>>(); | |
428 | ||
429 | let (_impl_display, assoc_ty_value_display) = s | |
430 | .db() | |
431 | .split_associated_ty_value_parameters(&display_params, self); | |
432 | ||
433 | write!(f, "{}type {}", s.indent(), assoc_ty_data.id.display(s))?; | |
434 | write_joined_non_empty_list!(f, "<{}>", &assoc_ty_value_display, ", ")?; | |
435 | write!(f, " = {};", value.ty.display(s))?; | |
436 | Ok(()) | |
437 | } | |
438 | } | |
439 | ||
440 | impl<I: Interner> RenderAsRust<I> for FnDefDatum<I> { | |
441 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { | |
442 | let s = &s.add_debrujin_index(None); | |
443 | let bound_datum = self.binders.skip_binders(); | |
444 | ||
445 | // declaration | |
446 | // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar | |
447 | // ^^^^^^ | |
448 | write!(f, "fn {}", s.db().fn_def_name(self.id))?; | |
449 | ||
450 | // binders | |
451 | // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar | |
452 | // ^^^ | |
453 | let binders = s.binder_var_display(&self.binders.binders); | |
454 | write_joined_non_empty_list!(f, "<{}>", binders, ", ")?; | |
455 | ||
456 | { | |
457 | let s = &s.add_debrujin_index(None); | |
458 | let inputs_and_output = bound_datum.inputs_and_output.skip_binders(); | |
459 | ||
460 | // arguments | |
461 | // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar | |
462 | // ^^^^^^^^^^^^^^^^^^^ | |
463 | let arguments = inputs_and_output | |
464 | .argument_types | |
465 | .iter() | |
466 | .enumerate() | |
467 | .map(|(idx, arg)| format!("arg_{}: {}", idx, arg.display(s))) | |
468 | .format(", "); | |
469 | ||
470 | write!(f, "({})", arguments)?; | |
471 | ||
472 | // return Type | |
473 | // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar | |
474 | // ^^^^^^^^^^^^^ | |
475 | write!(f, " -> {}", inputs_and_output.return_type.display(s))?; | |
476 | } | |
477 | ||
478 | // where clause | |
479 | // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar | |
480 | // ^^^^^^^^^^^^ | |
481 | if !bound_datum.where_clauses.is_empty() { | |
482 | let s = &s.add_indent(); | |
483 | write!(f, "\nwhere\n{}", bound_datum.where_clauses.display(s))?; | |
484 | } | |
485 | ||
486 | write!(f, ";")?; | |
487 | ||
488 | Ok(()) | |
489 | } | |
490 | } |