]> git.proxmox.com Git - rustc.git/blame - vendor/chalk-solve-0.25.0/src/display/items.rs
New upstream version 1.48.0+dfsg1
[rustc.git] / vendor / chalk-solve-0.25.0 / src / display / items.rs
CommitLineData
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
6use std::fmt::{Formatter, Result};
7
8use crate::rust_ir::*;
9use crate::split::Split;
10use chalk_ir::interner::Interner;
11use itertools::Itertools;
12
13use 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/// ```
45macro_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
66impl<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
152impl<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
161impl<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
230impl<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
303impl<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
327impl<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(&param_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
400impl<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(&param_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
440impl<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}