1 //! Writer logic for top level items.
3 //! Contains code specific to top-level items and other structures specific to a
4 //! single top-level item.
6 use std
::fmt
::{Formatter, Result}
;
9 use crate::split
::Split
;
10 use chalk_ir
::interner
::Interner
;
11 use itertools
::Itertools
;
14 display_self_where_clauses_as_bounds
, display_type_with_generics
, render_trait
::RenderAsRust
,
15 state
::InternalWriterState
,
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.
22 /// This macro will error if unknown flags are specified. This will also error
23 /// if any flags are missing.
28 /// write_flags!(f, self.flags, XFlags { red, green })
34 /// match self.flags {
35 /// XFlags { red, green } => {
37 /// write!(f, "#[red]")?;
40 /// write!(f, "#[green]")?;
45 macro_rules
! write_flags
{
46 ($writer
:ident
, $val
:expr
, $struct_name
:ident { $($n:ident $(: $extra_arg:tt)?),* }
) => {
48 // if any fields are missing, the destructuring will error
53 write
!($writer
, "#[{}]\n", write_flags
!(@
default $n $
(: $extra_arg
)*))?
;
58 (@
default $n
:ident
: $name
:literal
) => {
61 (@
default $n
:ident
) => {
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
70 let s
= &s
.add_debrujin_index(None
);
71 let value
= self.binders
.skip_binders();
86 let repr
= s
.db().adt_repr(self.id
);
93 repr_packed
: "repr(packed)"
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
),)?
,
103 write_joined_non_empty_list
!(f
, "<{}>", s
.binder_var_display(&self.binders
.binders
), ", ")?
;
106 if !value
.where_clauses
.is_empty() {
107 let s
= &s
.add_indent();
108 write
!(f
, "\nwhere\n{}\n", value
.where_clauses
.display(s
))?
;
115 let s
= &s
.add_indent();
117 AdtKind
::Struct
| AdtKind
::Union
=> {
118 write_joined_non_empty_list
!(
125 .map(|(idx
, field
)| {
126 format
!("{}field_{}: {}", s
.indent(), idx
, field
.display(s
))
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
!(
138 variant
.fields
.iter().enumerate().map(|(idx
, field
)| {
139 format
!("{}field_{}: {}", s
.indent(), idx
, field
.display(s
))
143 write
!(f
, "{}}},", s
.indent())?
;
152 impl<I
: Interner
> RenderAsRust
<I
> for Polarity
{
153 fn fmt(&self, _s
: &InternalWriterState
<'_
, I
>, f
: &'_
mut Formatter
<'_
>) -> Result
{
154 if !self.is_positive() {
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();
181 if s
.db().is_object_safe(self.id
) {
182 writeln
!(f
, "#[object_safe]")?
;
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",
197 writeln
!(f
, "#[lang({})]", name
)?
;
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
, ", ")?
;
206 if !value
.where_clauses
.is_empty() {
207 let s
= &s
.add_indent();
208 write
!(f
, "\nwhere\n{}\n", value
.where_clauses
.display(s
))?
;
215 let s
= &s
.add_indent();
216 write_joined_non_empty_list
!(
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
))
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();
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();
241 // impl<T> Foo<T> for Bar<T> where T: Baz { }
242 if self.impl_type
== ImplType
::External
{
243 writeln
!(f
, "#[upstream]")?
;
247 // impl<T> Foo<T> for Bar<T> where T: Baz { }
250 let trait_ref
= &value
.trait_ref
;
253 // impl<T> Foo<T> for Bar<T> where T: Baz
255 write_joined_non_empty_list
!(f
, "<{}>", binders
, ", ")?
;
257 // trait, type and parameters
258 // impl<T> Foo<T> for Bar<T> where T: Baz { }
260 let full_trait_name
= display_type_with_generics(
263 // Ignore automatically added Self parameter by skipping first parameter
264 &trait_ref
.substitution
.as_slice(interner
)[1..],
269 self.polarity
.display(s
),
271 trait_ref
.self_type_parameter(interner
).display(s
)
275 // impl<T> Foo<T> for Bar<T> where T: Baz { }
277 if !value
.where_clauses
.is_empty() {
278 let s
= &s
.add_indent();
279 write
!(f
, "\nwhere\n{}\n", value
.where_clauses
.display(s
))?
;
285 // impl<T> Foo<T> for Bar<T> where T: Baz { }
289 let s
= &s
.add_indent();
290 let assoc_ty_values
= self.associated_ty_value_ids
.iter().map(|assoc_ty_value
| {
292 .associated_ty_value(*assoc_ty_value
)
296 write_joined_non_empty_list
!(f
, "\n{}\n", assoc_ty_values
, "\n")?
;
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
), ", ")?
;
310 let s
= &s
.add_debrujin_index(Some(0));
311 let clauses
= bounds
.bounds
.skip_binders();
315 display_self_where_clauses_as_bounds(s
, clauses
)
321 s
.db().hidden_opaque_type(self.opaque_ty_id
).display(s
)
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
337 let trait_datum
= s
.db().trait_datum(self.trait_id
);
338 // inverted Debrujin indices for the trait's parameters in the trait
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
351 .split_associated_ty_parameters(¶m_names_in_assoc_ty_env
, self);
353 let s
= &s
.add_parameter_mapping(
354 trait_param_names_in_assoc_ty_env
.iter().copied(),
355 trait_param_names_in_trait_env
,
358 // rendered names for the associated type's generics in the associated
360 let binder_display_in_assoc_ty
= s
361 .binder_var_display(&self.binders
.binders
)
362 .collect
::<Vec
<_
>>();
364 let (_
, assoc_ty_params
) = s
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
, ", ")?
;
370 let datum_bounds
= &self.binders
.skip_binders();
372 if !datum_bounds
.bounds
.is_empty() {
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
381 .map(|bound
| bound
.display(s
).to_string())
383 write
!(f
, "{}", bounds
)?
;
385 // where_clause is 'X: Y, Z: D'
386 // type Foo<...>: ... where X: Y, Z: D;
388 // note: it's a quantified clause b/c we could have `for<'a> T: Foo<'a>`
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
)?
;
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
);
407 let impl_param_names_in_impl_env
= s
.binder_var_indices(&impl_datum
.binders
.binders
);
409 let s
= &s
.add_debrujin_index(None
);
410 let value
= self.value
.skip_binders();
412 let param_names_in_assoc_ty_value_env
= s
413 .binder_var_indices(&self.value
.binders
)
414 .collect
::<Vec
<_
>>();
416 let (impl_params_in_assoc_ty_value_env
, _assoc_ty_value_params
) = s
418 .split_associated_ty_value_parameters(¶m_names_in_assoc_ty_value_env
, self);
420 let s
= &s
.add_parameter_mapping(
421 impl_params_in_assoc_ty_value_env
.iter().cloned(),
422 impl_param_names_in_impl_env
,
425 let display_params
= s
426 .binder_var_display(&self.value
.binders
)
427 .collect
::<Vec
<_
>>();
429 let (_impl_display
, assoc_ty_value_display
) = s
431 .split_associated_ty_value_parameters(&display_params
, self);
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
))?
;
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();
446 // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
448 write
!(f
, "fn {}", s
.db().fn_def_name(self.id
))?
;
451 // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
453 let binders
= s
.binder_var_display(&self.binders
.binders
);
454 write_joined_non_empty_list
!(f
, "<{}>", binders
, ", ")?
;
457 let s
= &s
.add_debrujin_index(None
);
458 let inputs_and_output
= bound_datum
.inputs_and_output
.skip_binders();
461 // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
462 // ^^^^^^^^^^^^^^^^^^^
463 let arguments
= inputs_and_output
467 .map(|(idx
, arg
)| format
!("arg_{}: {}", idx
, arg
.display(s
)))
470 write
!(f
, "({})", arguments
)?
;
473 // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
475 write
!(f
, " -> {}", inputs_and_output
.return_type
.display(s
))?
;
479 // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
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
))?
;