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