1use crate::{
3 common::{TAB_INCR, repeat_except_first},
4 formatter::*,
5 gast,
6 llbc_ast::{self as llbc, *},
7 reorder_decls::*,
8 transform::utils::GenericsSource,
9 ullbc_ast::{self as ullbc, *},
10};
11use either::Either;
12use itertools::Itertools;
13use std::{
14 borrow::Cow,
15 fmt::{self, Debug, Display},
16};
17
18pub struct WithCtx<'a, C, T: ?Sized> {
19 val: &'a T,
20 ctx: &'a C,
21}
22
23impl<'a, C, T: ?Sized> Display for WithCtx<'a, C, T>
24where
25 T: FmtWithCtx<C>,
26{
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 self.val.fmt_with_ctx(self.ctx, f)
29 }
30}
31
32pub trait FmtWithCtx<C> {
34 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result;
35
36 fn with_ctx<'a>(&'a self, ctx: &'a C) -> WithCtx<'a, C, Self> {
41 WithCtx { val: self, ctx }
42 }
43
44 fn to_string_with_ctx(&self, ctx: &C) -> String {
45 self.with_ctx(ctx).to_string()
46 }
47}
48
49macro_rules! impl_display_via_ctx {
50 ($ty:ty) => {
51 impl Display for $ty {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 self.fmt_with_ctx(&FmtCtx::new(), f)
54 }
55 }
56 };
57}
58macro_rules! impl_debug_via_display {
59 ($ty:ty) => {
60 impl Debug for $ty {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 <_ as Display>::fmt(self, f)
63 }
64 }
65 };
66}
67
68impl<C: AstFormatter> FmtWithCtx<C> for AbortKind {
71 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 match self {
73 AbortKind::Panic(name) => {
74 write!(f, "panic")?;
75 if let Some(name) = name {
76 write!(f, "({})", name.with_ctx(ctx))?;
77 }
78 Ok(())
79 }
80 AbortKind::UndefinedBehavior => write!(f, "undefined_behavior"),
81 AbortKind::UnwindTerminate => write!(f, "unwind_terminate"),
82 }
83 }
84}
85
86impl<C: AstFormatter> FmtWithCtx<C> for AnyTransId {
87 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 match ctx
89 .get_crate()
90 .and_then(|translated| translated.item_short_name(*self))
91 {
92 None => write!(f, "{self}"),
93 Some(name) => name.fmt_with_ctx(ctx, f),
94 }
95 }
96}
97
98impl Display for AnyTransId {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
100 let s = match self {
101 AnyTransId::Type(x) => x.to_pretty_string(),
102 AnyTransId::Fun(x) => x.to_pretty_string(),
103 AnyTransId::Global(x) => x.to_pretty_string(),
104 AnyTransId::TraitDecl(x) => x.to_pretty_string(),
105 AnyTransId::TraitImpl(x) => x.to_pretty_string(),
106 };
107 f.write_str(&s)
108 }
109}
110
111impl<C: AstFormatter> FmtWithCtx<C> for AnyTransItem<'_> {
112 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 match self {
114 AnyTransItem::Type(d) => write!(f, "{}", d.with_ctx(ctx)),
115 AnyTransItem::Fun(d) => write!(f, "{}", d.with_ctx(ctx)),
116 AnyTransItem::Global(d) => write!(f, "{}", d.with_ctx(ctx)),
117 AnyTransItem::TraitDecl(d) => write!(f, "{}", d.with_ctx(ctx)),
118 AnyTransItem::TraitImpl(d) => write!(f, "{}", d.with_ctx(ctx)),
119 }
120 }
121}
122
123impl<C: AstFormatter> FmtWithCtx<C> for Assert {
124 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 write!(
126 f,
127 "assert({} == {})",
128 self.cond.with_ctx(ctx),
129 self.expected,
130 )
131 }
132}
133
134impl<T> Binder<T> {
135 fn fmt_split<'a, C>(&'a self, ctx: &'a C) -> (String, String)
138 where
139 C: AstFormatter,
140 T: FmtWithCtx<C::Reborrow<'a>>,
141 {
142 let ctx = &ctx.push_binder(Cow::Borrowed(&self.params));
143 (
144 self.params.fmt_with_ctx_single_line(ctx),
145 self.skip_binder.to_string_with_ctx(ctx),
146 )
147 }
148}
149
150impl Display for OverflowMode {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
152 match self {
153 OverflowMode::Panic => write!(f, "panic"),
154 OverflowMode::Wrap => write!(f, "wrap"),
155 OverflowMode::UB => write!(f, "ub"),
156 }
157 }
158}
159
160impl Display for BinOp {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
162 match self {
163 BinOp::BitXor => write!(f, "^"),
164 BinOp::BitAnd => write!(f, "&"),
165 BinOp::BitOr => write!(f, "|"),
166 BinOp::Eq => write!(f, "=="),
167 BinOp::Lt => write!(f, "<"),
168 BinOp::Le => write!(f, "<="),
169 BinOp::Ne => write!(f, "!="),
170 BinOp::Ge => write!(f, ">="),
171 BinOp::Gt => write!(f, ">"),
172 BinOp::Add(mode) => write!(f, "{}.+", mode),
173 BinOp::Sub(mode) => write!(f, "{}.-", mode),
174 BinOp::Mul(mode) => write!(f, "{}.*", mode),
175 BinOp::Div(mode) => write!(f, "{}./", mode),
176 BinOp::Rem(mode) => write!(f, "{}.%", mode),
177 BinOp::AddChecked => write!(f, "checked.+"),
178 BinOp::SubChecked => write!(f, "checked.-"),
179 BinOp::MulChecked => write!(f, "checked.*"),
180 BinOp::Shl(mode) => write!(f, "{}.<<", mode),
181 BinOp::Shr(mode) => write!(f, "{}.>>", mode),
182 BinOp::Cmp => write!(f, "cmp"),
183 BinOp::Offset => write!(f, "offset"),
184 }
185 }
186}
187
188impl<C: AstFormatter> FmtWithCtx<C> for llbc::Block {
189 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 for st in &self.statements {
191 writeln!(f, "{}", st.with_ctx(ctx))?;
192 }
193 Ok(())
194 }
195}
196
197impl<C: AstFormatter> FmtWithCtx<C> for ullbc::BlockData {
198 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 for statement in &self.statements {
200 writeln!(f, "{};", statement.with_ctx(ctx))?;
201 }
202 write!(f, "{};", self.terminator.with_ctx(ctx))?;
203 Ok(())
204 }
205}
206
207impl<C: AstFormatter> FmtWithCtx<C> for gast::Body {
208 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 match self {
210 Body::Unstructured(b) => write!(f, "{}", b.with_ctx(ctx)),
211 Body::Structured(b) => write!(f, "{}", b.with_ctx(ctx)),
212 }
213 }
214}
215
216impl Display for BorrowKind {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
218 write!(f, "{self:?}")
220 }
221}
222
223impl Display for BuiltinFunId {
224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
225 let name = match *self {
226 BuiltinFunId::BoxNew => "BoxNew",
227 BuiltinFunId::ArrayToSliceShared => "ArrayToSliceShared",
228 BuiltinFunId::ArrayToSliceMut => "ArrayToSliceMut",
229 BuiltinFunId::ArrayRepeat => "ArrayRepeat",
230 BuiltinFunId::Index(BuiltinIndexOp {
231 is_array,
232 mutability,
233 is_range,
234 }) => {
235 let ty = if is_array { "Array" } else { "Slice" };
236 let op = if is_range { "SubSlice" } else { "Index" };
237 let mutability = mutability.variant_name();
238 &format!("{ty}{op}{mutability}")
239 }
240 BuiltinFunId::PtrFromParts(mutability) => {
241 let mutability = mutability.variant_name();
242 &format!("PtrFromParts{mutability}")
243 }
244 };
245 f.write_str(name)
246 }
247}
248
249impl<C: AstFormatter> FmtWithCtx<C> for Call {
250 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 let dest = self.dest.with_ctx(ctx);
252 let func = self.func.with_ctx(ctx);
253 let args = self.args.iter().map(|x| x.with_ctx(ctx)).format(", ");
254 write!(f, "{dest} := {func}({args})")
255 }
256}
257
258impl<C: AstFormatter> FmtWithCtx<C> for CastKind {
259 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 match self {
261 CastKind::Scalar(src, tgt) => write!(f, "cast<{src}, {tgt}>"),
262 CastKind::FnPtr(src, tgt) | CastKind::RawPtr(src, tgt) => {
263 write!(f, "cast<{}, {}>", src.with_ctx(ctx), tgt.with_ctx(ctx))
264 }
265 CastKind::Unsize(src, tgt, meta) => {
266 write!(
267 f,
268 "unsize_cast<{}, {}",
269 src.with_ctx(ctx),
270 tgt.with_ctx(ctx),
271 )?;
272 match meta {
273 UnsizingMetadata::Length(len) => write!(f, ", {}", len.with_ctx(ctx))?,
274 UnsizingMetadata::VTablePtr(tref) => write!(f, ", {}", tref.with_ctx(ctx))?,
275 UnsizingMetadata::Unknown => {}
276 }
277 write!(f, ">")
278 }
279 CastKind::Transmute(src, tgt) => {
280 write!(f, "transmute<{}, {}>", src.with_ctx(ctx), tgt.with_ctx(ctx))
281 }
282 }
283 }
284}
285
286impl<C: AstFormatter> FmtWithCtx<C> for ClauseDbVar {
287 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288 ctx.format_bound_var(f, *self, "@TraitClause", |_| None)
289 }
290}
291
292impl_display_via_ctx!(ConstantExpr);
293impl<C: AstFormatter> FmtWithCtx<C> for ConstantExpr {
294 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 write!(f, "{}", self.value.with_ctx(ctx))
296 }
297}
298
299impl<C: AstFormatter> FmtWithCtx<C> for ConstGeneric {
300 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
301 match self {
302 ConstGeneric::Var(id) => write!(f, "{}", id.with_ctx(ctx)),
303 ConstGeneric::Value(v) => write!(f, "{v}"),
304 ConstGeneric::Global(id) => write!(f, "{}", id.with_ctx(ctx)),
305 }
306 }
307}
308
309impl<C: AstFormatter> FmtWithCtx<C> for ConstGenericDbVar {
310 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 ctx.format_bound_var(f, *self, "@ConstGeneric", |v| Some(v.to_string()))
312 }
313}
314
315impl_display_via_ctx!(ConstGenericVar);
316impl<C: AstFormatter> FmtWithCtx<C> for ConstGenericVar {
317 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
318 write!(f, "const {} : {}", self.name, self.ty)
319 }
320}
321
322impl Display for DeBruijnId {
323 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
324 write!(f, "{}", self.index)
325 }
326}
327
328impl<Id: Display> Display for DeBruijnVar<Id> {
329 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
330 match self {
331 Self::Bound(dbid, varid) => write!(f, "{dbid}_{varid}"),
332 Self::Free(varid) => write!(f, "{varid}"),
333 }
334 }
335}
336
337impl<C: AstFormatter> FmtWithCtx<C> for DeclarationGroup {
338 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339 use DeclarationGroup::*;
340 match self {
341 Type(g) => write!(f, "Type decls group: {}", g.with_ctx(ctx)),
342 Fun(g) => write!(f, "Fun decls group: {}", g.with_ctx(ctx)),
343 Global(g) => write!(f, "Global decls group: {}", g.with_ctx(ctx)),
344 TraitDecl(g) => write!(f, "Trait decls group: {}", g.with_ctx(ctx)),
345 TraitImpl(g) => write!(f, "Trait impls group: {}", g.with_ctx(ctx)),
346 Mixed(g) => write!(f, "Mixed group: {}", g.with_ctx(ctx)),
347 }
348 }
349}
350
351impl<C: AstFormatter> FmtWithCtx<C> for DynPredicate {
352 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 let ctx = &ctx.push_binder(Cow::Borrowed(&self.binder.params));
354 let ty = self.binder.skip_binder.with_ctx(ctx);
355 let clauses = self.binder.params.formatted_clauses(ctx).format(" + ");
356 write!(f, "exists<{ty}> {clauses}")
357 }
358}
359
360impl_display_via_ctx!(Field);
361impl<C: AstFormatter> FmtWithCtx<C> for Field {
362 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
363 if let Some(name) = &self.name {
364 write!(f, "{}: ", name)?
365 }
366 write!(f, "{}", self.ty.with_ctx(ctx))
367 }
368}
369
370impl Display for FileName {
371 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
372 match self {
373 FileName::Virtual(path_buf) | FileName::Local(path_buf) => {
374 write!(f, "{}", path_buf.display())
375 }
376 FileName::NotReal(name) => write!(f, "{}", name),
377 }
378 }
379}
380
381impl Display for FloatTy {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
383 match self {
384 FloatTy::F16 => write!(f, "f16"),
385 FloatTy::F32 => write!(f, "f32"),
386 FloatTy::F64 => write!(f, "f64"),
387 FloatTy::F128 => write!(f, "f128"),
388 }
389 }
390}
391
392impl Display for FloatValue {
393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
394 let v = &self.value;
395 match self.ty {
396 FloatTy::F16 => write!(f, "{v} : f16"),
397 FloatTy::F32 => write!(f, "{v} : f32"),
398 FloatTy::F64 => write!(f, "{v} : f64"),
399 FloatTy::F128 => write!(f, "{v} : f128"),
400 }
401 }
402}
403
404impl<C: AstFormatter> FmtWithCtx<C> for FnOperand {
405 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
406 match self {
407 FnOperand::Regular(func) => write!(f, "{}", func.with_ctx(ctx)),
408 FnOperand::Move(p) => write!(f, "(move {})", p.with_ctx(ctx)),
409 }
410 }
411}
412
413impl<C: AstFormatter> FmtWithCtx<C> for FnPtr {
414 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
415 match self.func.as_ref() {
416 FunIdOrTraitMethodRef::Fun(FunId::Regular(def_id)) => {
417 write!(f, "{}", def_id.with_ctx(ctx))?
418 }
419 FunIdOrTraitMethodRef::Fun(FunId::Builtin(builtin)) => write!(f, "@{}", builtin)?,
420 FunIdOrTraitMethodRef::Trait(trait_ref, method_id, _) => {
421 write!(f, "{}::{}", trait_ref.with_ctx(ctx), &method_id.0)?
422 }
423 };
424 write!(f, "{}", self.generics.with_ctx(ctx))
425 }
426}
427
428impl<C: AstFormatter> FmtWithCtx<C> for FunDecl {
429 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
430 let keyword = if self.signature.is_unsafe {
431 "unsafe fn"
432 } else {
433 "fn"
434 };
435 self.item_meta
436 .fmt_item_intro(f, ctx, keyword, self.def_id)?;
437
438 let ctx = &ctx.set_generics(&self.signature.generics);
440
441 let (params, preds) = self.signature.generics.fmt_with_ctx_with_trait_clauses(ctx);
443 write!(f, "{params}")?;
444
445 let mut args: Vec<String> = Vec::new();
447 for (i, ty) in self.signature.inputs.iter().enumerate() {
448 let id = LocalId::new(i + 1);
451 args.push(format!("{}: {}", id.to_pretty_string(), ty.with_ctx(ctx)));
452 }
453 let args = args.join(", ");
454 write!(f, "({args})")?;
455
456 if !self.signature.output.is_unit() {
458 write!(f, " -> {}", self.signature.output.with_ctx(ctx))?;
459 };
460 write!(f, "{preds}")?;
461
462 match &self.body {
464 Ok(body) => {
465 let tab = ctx.indent();
466 let body = body.with_ctx(ctx);
467 write!(f, "\n{tab}{{\n{body}{tab}}}")?;
468 }
469 Err(Opaque) => {}
470 }
471
472 Ok(())
473 }
474}
475
476impl<C: AstFormatter> FmtWithCtx<C> for FunDeclId {
477 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
479 }
480}
481
482impl<C: AstFormatter> FmtWithCtx<C> for FunDeclRef {
483 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484 let id = self.id.with_ctx(ctx);
485 let generics = self.generics.with_ctx(ctx);
486 write!(f, "{id}{generics}")
487 }
488}
489
490impl<C: AstFormatter> FmtWithCtx<C> for FunSig {
491 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492 let ctx = &ctx.set_generics(&self.generics);
493
494 if self.is_unsafe {
496 write!(f, "unsafe ")?;
497 }
498
499 let (params, clauses) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
501 write!(f, "fn{params}")?;
502
503 let args = self
505 .inputs
506 .iter()
507 .map(|ty| ty.with_ctx(ctx).to_string())
508 .format(", ");
509 write!(f, "({args})")?;
510
511 if !self.output.is_unit() {
513 write!(f, " -> {}", self.output.with_ctx(ctx))?;
514 }
515
516 write!(f, "{clauses}")?;
517 Ok(())
518 }
519}
520
521impl<Id: Copy, C: AstFormatter> FmtWithCtx<C> for GDeclarationGroup<Id>
522where
523 Id: FmtWithCtx<C>,
524{
525 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526 use GDeclarationGroup::*;
527 match self {
528 NonRec(id) => write!(f, "Non rec: {}", id.with_ctx(ctx)),
529 Rec(ids) => {
530 let ids = ids.iter().map(|id| id.with_ctx(ctx)).format(", ");
531 write!(f, "Rec: {}", ids)
532 }
533 }
534 }
535}
536
537impl GenericArgs {
538 pub(crate) fn fmt_explicits<'a, C: AstFormatter>(
539 &'a self,
540 ctx: &'a C,
541 ) -> impl Iterator<Item = impl Display + 'a> {
542 let regions = self.regions.iter().map(|x| x.with_ctx(ctx));
543 let types = self.types.iter().map(|x| x.with_ctx(ctx));
544 let const_generics = self.const_generics.iter().map(|x| x.with_ctx(ctx));
545 regions.map(Either::Left).chain(
546 types
547 .map(Either::Left)
548 .chain(const_generics.map(Either::Right))
549 .map(Either::Right),
550 )
551 }
552
553 pub(crate) fn fmt_implicits<'a, C: AstFormatter>(
554 &'a self,
555 ctx: &'a C,
556 ) -> impl Iterator<Item = impl Display + 'a> {
557 self.trait_refs.iter().map(|x| x.with_ctx(ctx))
558 }
559}
560
561impl_display_via_ctx!(GenericArgs);
562impl_debug_via_display!(GenericArgs);
563impl<C: AstFormatter> FmtWithCtx<C> for GenericArgs {
564 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565 if self.has_explicits() {
566 write!(f, "<{}>", self.fmt_explicits(ctx).format(", "))?;
567 }
568 if self.has_implicits() {
569 write!(f, "[{}]", self.fmt_implicits(ctx).format(", "))?;
570 }
571 Ok(())
572 }
573}
574
575impl GenericParams {
576 fn formatted_params<'a, C>(&'a self, ctx: &'a C) -> impl Iterator<Item = impl Display + 'a>
577 where
578 C: AstFormatter,
579 {
580 let regions = self.regions.iter().map(|x| x.with_ctx(ctx));
581 let types = self.types.iter();
582 let const_generics = self.const_generics.iter();
583 regions.map(Either::Left).chain(
584 types
585 .map(Either::Left)
586 .chain(const_generics.map(Either::Right))
587 .map(Either::Right),
588 )
589 }
590
591 fn formatted_clauses<'a, C>(&'a self, ctx: &'a C) -> impl Iterator<Item = impl Display + 'a>
592 where
593 C: AstFormatter,
594 {
595 let trait_clauses = self.trait_clauses.iter().map(|x| x.to_string_with_ctx(ctx));
596 let types_outlive = self.types_outlive.iter().map(|x| x.fmt_as_for(ctx));
597 let regions_outlive = self.regions_outlive.iter().map(|x| x.fmt_as_for(ctx));
598 let type_constraints = self
599 .trait_type_constraints
600 .iter()
601 .map(|x| x.fmt_as_for(ctx));
602 trait_clauses.map(Either::Left).chain(
603 types_outlive
604 .chain(regions_outlive)
605 .chain(type_constraints)
606 .map(Either::Right),
607 )
608 }
609
610 pub fn fmt_with_ctx_with_trait_clauses<C>(&self, ctx: &C) -> (String, String)
611 where
612 C: AstFormatter,
613 {
614 let tab = ctx.indent();
615 let params = if self.has_explicits() {
616 let params = self.formatted_params(ctx).format(", ");
617 format!("<{}>", params)
618 } else {
619 String::new()
620 };
621 let clauses = if self.has_predicates() {
622 let clauses = self
623 .formatted_clauses(ctx)
624 .map(|x| format!("\n{tab}{TAB_INCR}{x},"))
625 .format("");
626 format!("\n{tab}where{clauses}")
627 } else {
628 String::new()
629 };
630 (params, clauses)
631 }
632
633 pub fn fmt_with_ctx_single_line<C>(&self, ctx: &C) -> String
634 where
635 C: AstFormatter,
636 {
637 if self.is_empty() {
638 String::new()
639 } else {
640 let params = self
641 .formatted_params(ctx)
642 .map(Either::Left)
643 .chain(self.formatted_clauses(ctx).map(Either::Right))
644 .format(", ");
645 format!("<{}>", params)
646 }
647 }
648}
649
650impl_debug_via_display!(GenericParams);
651impl Display for GenericParams {
652 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
653 write!(f, "{}", self.fmt_with_ctx_single_line(&FmtCtx::new()))
654 }
655}
656
657impl<C: AstFormatter> FmtWithCtx<C> for GenericsSource {
658 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
659 match self {
660 GenericsSource::Item(id) => write!(f, "{}", id.with_ctx(ctx)),
661 GenericsSource::Method(id, name) => write!(f, "{}::{name}", id.with_ctx(ctx)),
662 GenericsSource::Builtin => write!(f, "<builtin>"),
663 GenericsSource::Other => write!(f, "<unknown>"),
664 }
665 }
666}
667
668impl<T> GExprBody<T> {
669 fn fmt_with_ctx_and_callback<C: AstFormatter>(
670 &self,
671 ctx: &C,
672 f: &mut fmt::Formatter<'_>,
673 fmt_body: impl FnOnce(
674 &mut fmt::Formatter<'_>,
675 &<<C as AstFormatter>::Reborrow<'_> as AstFormatter>::Reborrow<'_>,
676 &T,
677 ) -> fmt::Result,
678 ) -> fmt::Result {
679 let ctx = &ctx.set_locals(&self.locals);
681 let ctx = &ctx.increase_indent();
682 let tab = ctx.indent();
683
684 for v in &self.locals.locals {
686 write!(f, "{tab}")?;
687 write!(f, "let {v}: {};", v.ty.with_ctx(ctx))?;
688
689 write!(f, " // ")?;
690 let index = v.index.index();
691 if index == 0 {
692 write!(f, "return")?;
693 } else if index <= self.locals.arg_count {
694 write!(f, "arg #{index}")?
695 } else {
696 match &v.name {
697 Some(_) => write!(f, "local")?,
698 None => write!(f, "anonymous local")?,
699 }
700 }
701 writeln!(f)?;
702 }
703
704 fmt_body(f, ctx, &self.body)?;
705
706 Ok(())
707 }
708}
709
710impl<C: AstFormatter> FmtWithCtx<C> for GExprBody<llbc_ast::Block> {
711 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
712 fn fmt_body<C: AstFormatter>(
714 f: &mut fmt::Formatter<'_>,
715 ctx: &<<C as AstFormatter>::Reborrow<'_> as AstFormatter>::Reborrow<'_>,
716 body: &Block,
717 ) -> Result<(), fmt::Error> {
718 writeln!(f)?;
719 body.fmt_with_ctx(ctx, f)?;
720 Ok(())
721 }
722 self.fmt_with_ctx_and_callback(ctx, f, fmt_body::<C>)
723 }
724}
725impl<C: AstFormatter> FmtWithCtx<C> for GExprBody<ullbc_ast::BodyContents> {
726 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
727 fn fmt_body<C: AstFormatter>(
729 f: &mut fmt::Formatter<'_>,
730 ctx: &<<C as AstFormatter>::Reborrow<'_> as AstFormatter>::Reborrow<'_>,
731 body: &Vector<BlockId, BlockData>,
732 ) -> Result<(), fmt::Error> {
733 let tab = ctx.indent();
734 let ctx = &ctx.increase_indent();
735 for (bid, block) in body.iter_indexed_values() {
736 writeln!(f)?;
737 writeln!(f, "{tab}bb{}: {{", bid.index())?;
738 writeln!(f, "{}", block.with_ctx(ctx))?;
739 writeln!(f, "{tab}}}")?;
740 }
741 Ok(())
742 }
743 self.fmt_with_ctx_and_callback(ctx, f, fmt_body::<C>)
744 }
745}
746
747impl<C> FmtWithCtx<C> for GlobalDecl
748where
749 C: AstFormatter,
750{
751 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
752 let keyword = match self.global_kind {
753 GlobalKind::Static => "static",
754 GlobalKind::AnonConst | GlobalKind::NamedConst => "const",
755 };
756 self.item_meta
757 .fmt_item_intro(f, ctx, keyword, self.def_id)?;
758
759 let ctx = &ctx.set_generics(&self.generics);
761
762 let (params, preds) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
764
765 let ty = self.ty.with_ctx(ctx);
767 write!(f, "{params}: {ty}")?;
768
769 write!(f, "{preds}")?;
771 if self.generics.has_predicates() {
772 write!(f, "\n")?;
773 }
774 write!(f, " ")?;
775
776 let initializer = self.init.with_ctx(ctx);
778 write!(f, "= {initializer}()")?;
779
780 Ok(())
781 }
782}
783
784impl<C: AstFormatter> FmtWithCtx<C> for GlobalDeclId {
785 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
786 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
787 }
788}
789
790impl<C: AstFormatter> FmtWithCtx<C> for GlobalDeclRef {
791 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
792 let id = self.id.with_ctx(ctx);
793 let generics = self.generics.with_ctx(ctx);
794 write!(f, "{id}{generics}")
795 }
796}
797
798impl<C: AstFormatter> FmtWithCtx<C> for ImplElem {
799 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
800 write!(f, "{{")?;
801 match self {
802 ImplElem::Ty(bound_ty) => {
803 let ctx = ctx.set_generics(&bound_ty.params);
805 bound_ty.skip_binder.fmt_with_ctx(&ctx, f)?
806 }
807 ImplElem::Trait(impl_id) => {
808 match ctx.get_crate().and_then(|tr| tr.trait_impls.get(*impl_id)) {
809 None => write!(f, "impl#{impl_id}")?,
810 Some(timpl) => {
811 let ctx = &ctx.set_generics(&timpl.generics);
814 let mut impl_trait = timpl.impl_trait.clone();
815 let self_ty = impl_trait.generics.types.remove(TypeVarId::ZERO).unwrap();
816 write!(
817 f,
818 "impl {} for {}",
819 impl_trait.with_ctx(ctx),
820 self_ty.with_ctx(ctx)
821 )?;
822 }
823 }
824 }
825 }
826 write!(f, "}}")
827 }
828}
829
830impl Display for IntegerTy {
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
832 match self {
833 IntegerTy::Isize => write!(f, "isize"),
834 IntegerTy::I8 => write!(f, "i8"),
835 IntegerTy::I16 => write!(f, "i16"),
836 IntegerTy::I32 => write!(f, "i32"),
837 IntegerTy::I64 => write!(f, "i64"),
838 IntegerTy::I128 => write!(f, "i128"),
839 IntegerTy::Usize => write!(f, "usize"),
840 IntegerTy::U8 => write!(f, "u8"),
841 IntegerTy::U16 => write!(f, "u16"),
842 IntegerTy::U32 => write!(f, "u32"),
843 IntegerTy::U64 => write!(f, "u64"),
844 IntegerTy::U128 => write!(f, "u128"),
845 }
846 }
847}
848
849impl ItemMeta {
850 pub fn fmt_item_intro<C: AstFormatter>(
852 &self,
853 f: &mut fmt::Formatter<'_>,
854 ctx: &C,
855 keyword: &str,
856 id: impl Into<AnyTransId>,
857 ) -> fmt::Result {
858 let tab = ctx.indent();
859 let full_name = self.name.with_ctx(ctx);
860 let name = if let Some(tr) = ctx.get_crate()
861 && let Some(short_name) = tr.short_names.get(&id.into())
862 {
863 writeln!(f, "// Full name: {full_name}")?;
864 short_name.with_ctx(ctx)
865 } else {
866 full_name
867 };
868 if let Some(id) = &self.lang_item {
869 writeln!(f, "{tab}#[lang_item(\"{id}\")]")?;
870 }
871 write!(f, "{tab}")?;
872 if self.attr_info.public {
873 write!(f, "pub ")?;
874 }
875 write!(f, "{keyword} {name}")
876 }
877}
878
879impl Display for Literal {
880 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
881 match self {
882 Literal::Scalar(v) => write!(f, "{v}"),
883 Literal::Float(v) => write!(f, "{v}"),
884 Literal::Bool(v) => write!(f, "{v}"),
885 Literal::Char(v) => write!(f, "{v}"),
886 Literal::Str(v) => write!(f, "\"{}\"", v.replace("\\", "\\\\").replace("\n", "\\n")),
887 Literal::ByteStr(v) => write!(f, "{v:?}"),
888 }
889 }
890}
891
892impl Display for LiteralTy {
893 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
894 match self {
895 LiteralTy::Integer(ty) => write!(f, "{ty}"),
896 LiteralTy::Float(ty) => write!(f, "{ty}"),
897 LiteralTy::Char => write!(f, "char"),
898 LiteralTy::Bool => write!(f, "bool"),
899 }
900 }
901}
902
903impl Display for Loc {
904 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
905 write!(f, "{}:{}", self.line, self.col)
906 }
907}
908
909impl Display for Local {
910 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
911 if let Some(name) = &self.name {
914 write!(f, "{name}")?
915 }
916 write!(f, "{}", self.index.to_pretty_string())?;
917 Ok(())
918 }
919}
920
921impl<C: AstFormatter> FmtWithCtx<C> for LocalId {
922 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
923 ctx.format_local_id(f, *self)
924 }
925}
926
927impl<C: AstFormatter> FmtWithCtx<C> for Name {
928 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
929 let name = self.name.iter().map(|x| x.with_ctx(ctx)).format("::");
930 write!(f, "{}", name)
931 }
932}
933
934impl<C: AstFormatter> FmtWithCtx<C> for NullOp {
935 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
936 let op = match self {
937 NullOp::SizeOf => "size_of",
938 NullOp::AlignOf => "align_of",
939 NullOp::OffsetOf(_) => "offset_of(?)",
940 NullOp::UbChecks => "ub_checks",
941 };
942 write!(f, "{op}")
943 }
944}
945
946impl_display_via_ctx!(Operand);
947impl<C: AstFormatter> FmtWithCtx<C> for Operand {
948 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
949 match self {
950 Operand::Copy(p) => write!(f, "copy ({})", p.with_ctx(ctx)),
951 Operand::Move(p) => write!(f, "move ({})", p.with_ctx(ctx)),
952 Operand::Const(c) => write!(f, "const ({})", c.with_ctx(ctx)),
953 }
954 }
955}
956
957impl<C: AstFormatter, T, U> FmtWithCtx<C> for OutlivesPred<T, U>
958where
959 T: FmtWithCtx<C>,
960 U: FmtWithCtx<C>,
961{
962 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
963 write!(f, "{} : {}", self.0.with_ctx(ctx), self.1.with_ctx(ctx))
964 }
965}
966
967impl<C: AstFormatter> FmtWithCtx<C> for PathElem {
968 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
969 match self {
970 PathElem::Ident(s, d) => {
971 write!(f, "{s}")?;
972 if !d.is_zero() {
973 write!(f, "#{}", d)?;
974 }
975 Ok(())
976 }
977 PathElem::Impl(impl_elem) => {
978 write!(f, "{}", impl_elem.with_ctx(ctx))
979 }
980 PathElem::Monomorphized(args) => {
981 write!(f, "<{}>", args.fmt_explicits(ctx).format(", "))
982 }
983 }
984 }
985}
986
987impl_display_via_ctx!(Place);
988impl<C: AstFormatter> FmtWithCtx<C> for Place {
989 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
990 match &self.kind {
991 PlaceKind::Local(var_id) => write!(f, "{}", var_id.with_ctx(ctx)),
992 PlaceKind::Projection(subplace, projection) => {
993 let sub = subplace.with_ctx(ctx);
994 match projection {
995 ProjectionElem::Deref => {
996 write!(f, "*({sub})")
997 }
998 ProjectionElem::Field(proj_kind, field_id) => match proj_kind {
999 FieldProjKind::Adt(adt_id, opt_variant_id) => {
1000 write!(f, "({sub}")?;
1001 if let Some(variant_id) = opt_variant_id {
1002 write!(f, " as variant ")?;
1003 ctx.format_enum_variant(f, *adt_id, *variant_id)?;
1004 }
1005 write!(f, ").")?;
1006 ctx.format_field_name(f, *adt_id, *opt_variant_id, *field_id)?;
1007 Ok(())
1008 }
1009 FieldProjKind::Tuple(_) => {
1010 write!(f, "({sub}).{field_id}")
1011 }
1012 },
1013 ProjectionElem::Index {
1014 offset,
1015 from_end: true,
1016 ..
1017 } => write!(f, "({sub})[-{}]", offset.with_ctx(ctx)),
1018 ProjectionElem::Index {
1019 offset,
1020 from_end: false,
1021 ..
1022 } => write!(f, "({sub})[{}]", offset.with_ctx(ctx)),
1023 ProjectionElem::Subslice {
1024 from,
1025 to,
1026 from_end: true,
1027 ..
1028 } => write!(f, "({sub})[{}..-{}]", from.with_ctx(ctx), to.with_ctx(ctx)),
1029 ProjectionElem::Subslice {
1030 from,
1031 to,
1032 from_end: false,
1033 ..
1034 } => write!(f, "({sub})[{}..{}]", from.with_ctx(ctx), to.with_ctx(ctx)),
1035 }
1036 }
1037 }
1038 }
1039}
1040
1041impl<C: AstFormatter> FmtWithCtx<C> for PolyTraitDeclRef {
1042 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1043 write!(f, "{}", self.fmt_as_for(ctx))
1044 }
1045}
1046
1047impl Display for RawAttribute {
1048 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1049 write!(f, "{}", self.path)?;
1050 if let Some(args) = &self.args {
1051 write!(f, "({args})")?;
1052 }
1053 Ok(())
1054 }
1055}
1056
1057impl<C: AstFormatter> FmtWithCtx<C> for RawConstantExpr {
1058 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1059 match self {
1060 RawConstantExpr::Literal(c) => write!(f, "{}", c.to_string()),
1061 RawConstantExpr::Adt(variant_id, values) => {
1062 let variant_id = match variant_id {
1066 Some(id) => format!("Some({id})"),
1067 None => "None".to_string(),
1068 };
1069 let values = values.iter().map(|v| v.with_ctx(ctx)).format(", ");
1070 write!(f, "ConstAdt {} [{}]", variant_id, values)
1071 }
1072 RawConstantExpr::Array(values) => {
1073 let values = values.iter().map(|v| v.with_ctx(ctx)).format(", ");
1074 write!(f, "[{}]", values)
1075 }
1076 RawConstantExpr::Global(global_ref) => {
1077 write!(f, "{}", global_ref.with_ctx(ctx))
1078 }
1079 RawConstantExpr::TraitConst(trait_ref, name) => {
1080 write!(f, "{}::{name}", trait_ref.with_ctx(ctx),)
1081 }
1082 RawConstantExpr::Ref(cv) => {
1083 write!(f, "&{}", cv.with_ctx(ctx))
1084 }
1085 RawConstantExpr::Ptr(rk, cv) => match rk {
1086 RefKind::Mut => write!(f, "&raw mut {}", cv.with_ctx(ctx)),
1087 RefKind::Shared => write!(f, "&raw const {}", cv.with_ctx(ctx)),
1088 },
1089 RawConstantExpr::Var(id) => write!(f, "{}", id.with_ctx(ctx)),
1090 RawConstantExpr::FnPtr(fp) => {
1091 write!(f, "{}", fp.with_ctx(ctx))
1092 }
1093 RawConstantExpr::RawMemory(bytes) => write!(f, "RawMemory({bytes:?})"),
1094 RawConstantExpr::Opaque(cause) => write!(f, "Opaque({cause})"),
1095 }
1096 }
1097}
1098
1099impl<C: AstFormatter> FmtWithCtx<C> for Region {
1100 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1101 match self {
1102 Region::Static => write!(f, "'static"),
1103 Region::Var(var) => write!(f, "{}", var.with_ctx(ctx)),
1104 Region::Erased => write!(f, "'_"),
1105 }
1106 }
1107}
1108
1109impl<T> RegionBinder<T> {
1110 fn fmt_split<'a, C>(&'a self, ctx: &'a C) -> (String, String)
1112 where
1113 C: AstFormatter,
1114 T: FmtWithCtx<C::Reborrow<'a>>,
1115 {
1116 let ctx = &ctx.push_bound_regions(&self.regions);
1117 (
1118 self.regions
1119 .iter()
1120 .map(|r| r.with_ctx(ctx))
1121 .format(", ")
1122 .to_string(),
1123 self.skip_binder.to_string_with_ctx(ctx),
1124 )
1125 }
1126
1127 fn fmt_as_for<'a, C>(&'a self, ctx: &'a C) -> String
1129 where
1130 C: AstFormatter,
1131 T: FmtWithCtx<C::Reborrow<'a>>,
1132 {
1133 let (regions, value) = self.fmt_split(ctx);
1134 let regions = if regions.is_empty() {
1135 "".to_string()
1136 } else {
1137 format!("for<{regions}> ",)
1138 };
1139 format!("{regions}{value}",)
1140 }
1141}
1142
1143impl<C: AstFormatter> FmtWithCtx<C> for RegionDbVar {
1144 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1145 ctx.format_bound_var(f, *self, "'_", |v| {
1146 v.name.as_ref().map(|name| name.to_string())
1147 })
1148 }
1149}
1150
1151impl_display_via_ctx!(RegionVar);
1152impl<C: AstFormatter> FmtWithCtx<C> for RegionVar {
1153 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1154 match &self.name {
1155 Some(name) => write!(f, "{name}"),
1156 None => write!(f, "'_{}", self.index),
1157 }
1158 }
1159}
1160
1161impl_display_via_ctx!(Rvalue);
1162impl<C: AstFormatter> FmtWithCtx<C> for Rvalue {
1163 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1164 match self {
1165 Rvalue::Use(x) => write!(f, "{}", x.with_ctx(ctx)),
1166 Rvalue::Ref(place, borrow_kind) => {
1167 let borrow_kind = match borrow_kind {
1168 BorrowKind::Shared => "&",
1169 BorrowKind::Mut => "&mut ",
1170 BorrowKind::TwoPhaseMut => "&two-phase-mut ",
1171 BorrowKind::UniqueImmutable => "&uniq ",
1172 BorrowKind::Shallow => "&shallow ",
1173 };
1174 write!(f, "{borrow_kind}{}", place.with_ctx(ctx))
1175 }
1176 Rvalue::RawPtr(place, mutability) => {
1177 let ptr_kind = match mutability {
1178 RefKind::Shared => "&raw const ",
1179 RefKind::Mut => "&raw mut ",
1180 };
1181 write!(f, "{ptr_kind}{}", place.with_ctx(ctx))
1182 }
1183
1184 Rvalue::BinaryOp(binop, x, y) => {
1185 write!(f, "{} {} {}", x.with_ctx(ctx), binop, y.with_ctx(ctx))
1186 }
1187 Rvalue::UnaryOp(unop, x) => {
1188 write!(f, "{}({})", unop.with_ctx(ctx), x.with_ctx(ctx))
1189 }
1190 Rvalue::NullaryOp(op, ty) => {
1191 write!(f, "{}<{}>", op.with_ctx(ctx), ty.with_ctx(ctx))
1192 }
1193 Rvalue::Discriminant(p, _) => {
1194 write!(f, "@discriminant({})", p.with_ctx(ctx),)
1195 }
1196 Rvalue::Aggregate(kind, ops) => {
1197 let ops_s = ops.iter().map(|op| op.with_ctx(ctx)).format(", ");
1198 match kind {
1199 AggregateKind::Adt(ty_ref, variant_id, field_id) => {
1200 match ty_ref.id {
1201 TypeId::Tuple => write!(f, "({})", ops_s),
1202 TypeId::Builtin(_) => unreachable!(),
1203 TypeId::Adt(ty_id) => {
1204 match variant_id {
1205 None => ty_id.fmt_with_ctx(ctx, f)?,
1206 Some(variant_id) => {
1207 ctx.format_enum_variant(f, ty_id, *variant_id)?
1208 }
1209 }
1210 write!(f, " {{ ")?;
1211 for (comma, (i, op)) in
1212 repeat_except_first(", ").zip(ops.iter().enumerate())
1213 {
1214 write!(f, "{}", comma.unwrap_or_default())?;
1215 let field_id = match *field_id {
1216 None => FieldId::new(i),
1217 Some(field_id) => {
1218 assert_eq!(i, 0); field_id
1220 }
1221 };
1222 ctx.format_field_name(f, ty_id, *variant_id, field_id)?;
1223 write!(f, ": {}", op.with_ctx(ctx))?;
1224 }
1225 write!(f, " }}")
1226 }
1227 }
1228 }
1229 AggregateKind::Array(..) => {
1230 write!(f, "[{}]", ops_s)
1231 }
1232 AggregateKind::RawPtr(_, rmut) => {
1233 let mutability = match rmut {
1234 RefKind::Shared => "const",
1235 RefKind::Mut => "mut ",
1236 };
1237 write!(f, "*{} ({})", mutability, ops_s)
1238 }
1239 }
1240 }
1241 Rvalue::Global(global_ref) => write!(f, "{}", global_ref.with_ctx(ctx)),
1242 Rvalue::GlobalRef(global_ref, RefKind::Shared) => {
1243 write!(f, "&{}", global_ref.with_ctx(ctx))
1244 }
1245 Rvalue::GlobalRef(global_ref, RefKind::Mut) => {
1246 write!(f, "&raw mut {}", global_ref.with_ctx(ctx))
1247 }
1248 Rvalue::Len(place, ..) => write!(f, "len({})", place.with_ctx(ctx)),
1249 Rvalue::Repeat(op, _ty, cg) => {
1250 write!(f, "[{}; {}]", op.with_ctx(ctx), cg.with_ctx(ctx))
1251 }
1252 Rvalue::ShallowInitBox(op, ty) => {
1253 write!(
1254 f,
1255 "shallow_init_box::<{}>({})",
1256 ty.with_ctx(ctx),
1257 op.with_ctx(ctx)
1258 )
1259 }
1260 }
1261 }
1262}
1263
1264impl Display for ScalarValue {
1265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1266 match self {
1267 ScalarValue::Isize(v) => write!(f, "{v} : isize"),
1268 ScalarValue::I8(v) => write!(f, "{v} : i8"),
1269 ScalarValue::I16(v) => write!(f, "{v} : i16"),
1270 ScalarValue::I32(v) => write!(f, "{v} : i32"),
1271 ScalarValue::I64(v) => write!(f, "{v} : i64"),
1272 ScalarValue::I128(v) => write!(f, "{v} : i128"),
1273 ScalarValue::Usize(v) => write!(f, "{v} : usize"),
1274 ScalarValue::U8(v) => write!(f, "{v} : u8"),
1275 ScalarValue::U16(v) => write!(f, "{v} : u16"),
1276 ScalarValue::U32(v) => write!(f, "{v} : u32"),
1277 ScalarValue::U64(v) => write!(f, "{v} : u64"),
1278 ScalarValue::U128(v) => write!(f, "{v} : u128"),
1279 }
1280 }
1281}
1282
1283impl<C: AstFormatter> FmtWithCtx<C> for ullbc::Statement {
1284 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1285 let tab = ctx.indent();
1286 use ullbc::RawStatement;
1287 for line in &self.comments_before {
1288 writeln!(f, "{tab}// {line}")?;
1289 }
1290 match &self.content {
1291 RawStatement::Assign(place, rvalue) => write!(
1292 f,
1293 "{tab}{} := {}",
1294 place.with_ctx(ctx),
1295 rvalue.with_ctx(ctx),
1296 ),
1297 RawStatement::SetDiscriminant(place, variant_id) => write!(
1298 f,
1299 "{tab}@discriminant({}) := {}",
1300 place.with_ctx(ctx),
1301 variant_id
1302 ),
1303 RawStatement::CopyNonOverlapping(box CopyNonOverlapping { src, dst, count }) => write!(
1304 f,
1305 "{}copy_nonoverlapping({}, {}, {})",
1306 tab,
1307 src.with_ctx(ctx),
1308 dst.with_ctx(ctx),
1309 count.with_ctx(ctx),
1310 ),
1311 RawStatement::StorageLive(var_id) => {
1312 write!(f, "{tab}storage_live({})", var_id.with_ctx(ctx))
1313 }
1314 RawStatement::StorageDead(var_id) => {
1315 write!(f, "{tab}storage_dead({})", var_id.with_ctx(ctx))
1316 }
1317 RawStatement::Deinit(place) => {
1318 write!(f, "{tab}deinit({})", place.with_ctx(ctx))
1319 }
1320 RawStatement::Drop(place, tref) => {
1321 write!(
1322 f,
1323 "{tab}drop[{}] {}",
1324 tref.with_ctx(ctx),
1325 place.with_ctx(ctx),
1326 )
1327 }
1328 RawStatement::Assert(assert) => write!(f, "{tab}{}", assert.with_ctx(ctx)),
1329 RawStatement::Nop => write!(f, "{tab}nop"),
1330 RawStatement::Error(s) => write!(f, "{tab}@Error({})", s),
1331 }
1332 }
1333}
1334
1335impl<C: AstFormatter> FmtWithCtx<C> for llbc::Statement {
1336 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1337 let tab = ctx.indent();
1338 use llbc::RawStatement;
1339 for line in &self.comments_before {
1340 writeln!(f, "{tab}// {line}")?;
1341 }
1342 write!(f, "{tab}")?;
1343 match &self.content {
1344 RawStatement::Assign(place, rvalue) => {
1345 write!(f, "{} := {}", place.with_ctx(ctx), rvalue.with_ctx(ctx),)
1346 }
1347 RawStatement::SetDiscriminant(place, variant_id) => write!(
1348 f,
1349 "@discriminant({}) := {}",
1350 place.with_ctx(ctx),
1351 variant_id
1352 ),
1353 RawStatement::CopyNonOverlapping(box CopyNonOverlapping { src, dst, count }) => write!(
1354 f,
1355 "copy_nonoverlapping({}, {}, {})",
1356 src.with_ctx(ctx),
1357 dst.with_ctx(ctx),
1358 count.with_ctx(ctx),
1359 ),
1360 RawStatement::StorageLive(var_id) => {
1361 write!(f, "storage_live({})", var_id.with_ctx(ctx))
1362 }
1363 RawStatement::StorageDead(var_id) => {
1364 write!(f, "storage_dead({})", var_id.with_ctx(ctx))
1365 }
1366 RawStatement::Deinit(place) => {
1367 write!(f, "deinit({})", place.with_ctx(ctx))
1368 }
1369 RawStatement::Drop(place, tref) => {
1370 write!(f, "drop[{}] {}", tref.with_ctx(ctx), place.with_ctx(ctx),)
1371 }
1372 RawStatement::Assert(assert) => {
1373 write!(f, "{}", assert.with_ctx(ctx),)
1374 }
1375 RawStatement::Call(call) => {
1376 write!(f, "{}", call.with_ctx(ctx))
1377 }
1378 RawStatement::Abort(kind) => {
1379 write!(f, "{}", kind.with_ctx(ctx))
1380 }
1381 RawStatement::Return => write!(f, "return"),
1382 RawStatement::Break(index) => write!(f, "break {index}"),
1383 RawStatement::Continue(index) => write!(f, "continue {index}"),
1384 RawStatement::Nop => write!(f, "nop"),
1385 RawStatement::Switch(switch) => match switch {
1386 Switch::If(discr, true_st, false_st) => {
1387 let ctx = &ctx.increase_indent();
1388 write!(
1389 f,
1390 "if {} {{\n{}{tab}}}\n{tab}else {{\n{}{tab}}}",
1391 discr.with_ctx(ctx),
1392 true_st.with_ctx(ctx),
1393 false_st.with_ctx(ctx),
1394 )
1395 }
1396 Switch::SwitchInt(discr, _ty, maps, otherwise) => {
1397 writeln!(f, "switch {} {{", discr.with_ctx(ctx))?;
1398 let ctx1 = &ctx.increase_indent();
1399 let inner_tab1 = ctx1.indent();
1400 let ctx2 = &ctx1.increase_indent();
1401 for (pvl, st) in maps {
1402 let pvl = pvl.iter().format(" | ");
1404 writeln!(
1405 f,
1406 "{inner_tab1}{} => {{\n{}{inner_tab1}}},",
1407 pvl,
1408 st.with_ctx(ctx2),
1409 )?;
1410 }
1411 writeln!(
1412 f,
1413 "{inner_tab1}_ => {{\n{}{inner_tab1}}},",
1414 otherwise.with_ctx(ctx2),
1415 )?;
1416 write!(f, "{tab}}}")
1417 }
1418 Switch::Match(discr, maps, otherwise) => {
1419 writeln!(f, "match {} {{", discr.with_ctx(ctx))?;
1420 let ctx1 = &ctx.increase_indent();
1421 let inner_tab1 = ctx1.indent();
1422 let ctx2 = &ctx1.increase_indent();
1423 let discr_type: Option<TypeDeclId> = discr
1424 .ty
1425 .kind()
1426 .as_adt()
1427 .and_then(|tref| tref.id.as_adt())
1428 .copied();
1429 for (cases, st) in maps {
1430 write!(f, "{inner_tab1}",)?;
1431 for (bar, v) in repeat_except_first(" | ").zip(cases.iter()) {
1433 write!(f, "{}", bar.unwrap_or_default())?;
1434 match discr_type {
1435 Some(type_id) => ctx.format_enum_variant(f, type_id, *v)?,
1436 None => write!(f, "{}", v.to_pretty_string())?,
1437 }
1438 }
1439 writeln!(f, " => {{\n{}{inner_tab1}}},", st.with_ctx(ctx2),)?;
1440 }
1441 if let Some(otherwise) = otherwise {
1442 writeln!(
1443 f,
1444 "{inner_tab1}_ => {{\n{}{inner_tab1}}},",
1445 otherwise.with_ctx(ctx2),
1446 )?;
1447 }
1448 write!(f, "{tab}}}")
1449 }
1450 },
1451 RawStatement::Loop(body) => {
1452 let ctx = &ctx.increase_indent();
1453 write!(f, "loop {{\n{}{tab}}}", body.with_ctx(ctx))
1454 }
1455 RawStatement::Error(s) => write!(f, "@ERROR({})", s),
1456 }
1457 }
1458}
1459
1460impl<C: AstFormatter> FmtWithCtx<C> for Terminator {
1461 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1462 let tab = ctx.indent();
1463 for line in &self.comments_before {
1464 writeln!(f, "{tab}// {line}")?;
1465 }
1466 write!(f, "{tab}")?;
1467 match &self.content {
1468 RawTerminator::Goto { target } => write!(f, "goto bb{target}"),
1469 RawTerminator::Switch { discr, targets } => match targets {
1470 SwitchTargets::If(true_block, false_block) => write!(
1471 f,
1472 "if {} -> bb{} else -> bb{}",
1473 discr.with_ctx(ctx),
1474 true_block,
1475 false_block
1476 ),
1477 SwitchTargets::SwitchInt(_ty, maps, otherwise) => {
1478 let maps = maps
1479 .iter()
1480 .map(|(v, bid)| format!("{}: bb{}", v.to_string(), bid))
1481 .chain([format!("otherwise: bb{otherwise}")])
1482 .format(", ");
1483 write!(f, "switch {} -> {}", discr.with_ctx(ctx), maps)
1484 }
1485 },
1486 RawTerminator::Call {
1487 call,
1488 target,
1489 on_unwind,
1490 } => {
1491 let call = call.with_ctx(ctx);
1492 write!(f, "{call} -> bb{target} (unwind: bb{on_unwind})",)
1493 }
1494 RawTerminator::Abort(kind) => write!(f, "{}", kind.with_ctx(ctx)),
1495 RawTerminator::Return => write!(f, "return"),
1496 RawTerminator::UnwindResume => write!(f, "unwind_continue"),
1497 }
1498 }
1499}
1500
1501impl<C: AstFormatter> FmtWithCtx<C> for TraitClause {
1502 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1503 let clause_id = self.clause_id.to_pretty_string();
1504 let trait_ = self.trait_.with_ctx(ctx);
1505 write!(f, "[{clause_id}]: {trait_}")
1506 }
1507}
1508
1509impl<C: AstFormatter> FmtWithCtx<C> for TraitDecl {
1510 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1511 let ctx = &ctx.set_generics(&self.generics);
1513
1514 self.item_meta
1515 .fmt_item_intro(f, ctx, "trait", self.def_id)?;
1516
1517 let (generics, clauses) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
1518 write!(f, "{generics}{clauses}")?;
1519
1520 let any_item = !self.parent_clauses.is_empty()
1521 || !self.type_clauses.is_empty()
1522 || !self.consts.is_empty()
1523 || !self.types.is_empty()
1524 || self.methods().count() > 0;
1525 if any_item {
1526 write!(f, "\n{{\n")?;
1527 for c in &self.parent_clauses {
1528 writeln!(
1529 f,
1530 "{TAB_INCR}parent_clause{} : {}",
1531 c.clause_id,
1532 c.with_ctx(ctx)
1533 )?;
1534 }
1535 for (name, clauses) in &self.type_clauses {
1536 for c in clauses {
1537 writeln!(
1538 f,
1539 "{TAB_INCR}item_clause_{name}_{} : {}",
1540 c.clause_id.to_string(),
1541 c.with_ctx(ctx)
1542 )?;
1543 }
1544 }
1545 for (name, ty) in &self.consts {
1546 let ty = ty.with_ctx(ctx);
1547 writeln!(f, "{TAB_INCR}const {name} : {ty}")?;
1548 }
1549 for name in &self.types {
1550 writeln!(f, "{TAB_INCR}type {name}")?;
1551 }
1552 for (name, bound_fn) in self.methods() {
1553 let (params, fn_ref) = bound_fn.fmt_split(ctx);
1554 writeln!(f, "{TAB_INCR}fn {name}{params} = {fn_ref}")?;
1555 }
1556 write!(f, "}}")?;
1557 }
1558 Ok(())
1559 }
1560}
1561
1562impl<C: AstFormatter> FmtWithCtx<C> for TraitDeclId {
1563 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1564 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
1565 }
1566}
1567
1568impl<C: AstFormatter> FmtWithCtx<C> for TraitDeclRef {
1569 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1570 let trait_id = self.id.with_ctx(ctx);
1571 let generics = self.generics.with_ctx(ctx);
1572 write!(f, "{trait_id}{generics}")
1573 }
1574}
1575
1576impl<C: AstFormatter> FmtWithCtx<C> for TraitImpl {
1577 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1578 let full_name = self.item_meta.name.with_ctx(ctx);
1579 writeln!(f, "// Full name: {full_name}")?;
1580
1581 let ctx = &ctx.set_generics(&self.generics);
1583
1584 let (generics, clauses) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
1585 let mut impl_trait = self.impl_trait.clone();
1586 let self_ty = impl_trait.generics.types.remove(TypeVarId::ZERO).unwrap();
1587 let self_ty = self_ty.with_ctx(ctx);
1588 let impl_trait = impl_trait.with_ctx(ctx);
1589 write!(f, "impl{generics} {impl_trait} for {self_ty}{clauses}")?;
1590
1591 let newline = if clauses.is_empty() {
1592 " ".to_string()
1593 } else {
1594 "\n".to_string()
1595 };
1596 write!(f, "{newline}{{")?;
1597
1598 let any_item = !self.parent_trait_refs.is_empty()
1599 || !self.type_clauses.is_empty()
1600 || !self.consts.is_empty()
1601 || !self.types.is_empty()
1602 || self.methods().count() > 0;
1603 if any_item {
1604 writeln!(f)?;
1605 for (i, c) in self.parent_trait_refs.iter().enumerate() {
1606 let i = TraitClauseId::new(i);
1607 writeln!(f, "{TAB_INCR}parent_clause{i} = {}", c.with_ctx(ctx))?;
1608 }
1609 for (name, clauses) in &self.type_clauses {
1610 for (i, c) in clauses.iter().enumerate() {
1611 let i = TraitClauseId::new(i);
1612 writeln!(f, "{TAB_INCR}item_clause_{name}_{i} = {}", c.with_ctx(ctx))?;
1613 }
1614 }
1615 for (name, global) in &self.consts {
1616 writeln!(f, "{TAB_INCR}const {name} = {}", global.with_ctx(ctx))?;
1617 }
1618 for (name, ty) in &self.types {
1619 writeln!(f, "{TAB_INCR}type {name} = {}", ty.with_ctx(ctx))?;
1620 }
1621 for (name, bound_fn) in self.methods() {
1622 let (params, fn_ref) = bound_fn.fmt_split(ctx);
1623 writeln!(f, "{TAB_INCR}fn {name}{params} = {fn_ref}")?;
1624 }
1625 }
1626 write!(f, "}}")?;
1627 Ok(())
1628 }
1629}
1630
1631impl<C: AstFormatter> FmtWithCtx<C> for TraitImplId {
1632 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1633 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
1634 }
1635}
1636
1637impl<C: AstFormatter> FmtWithCtx<C> for TraitImplRef {
1638 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1639 let id = self.id.with_ctx(ctx);
1640 let generics = self.generics.with_ctx(ctx);
1641 write!(f, "{id}{generics}")
1642 }
1643}
1644
1645impl Display for TraitItemName {
1646 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1647 write!(f, "{}", self.0)
1648 }
1649}
1650
1651impl<C: AstFormatter> FmtWithCtx<C> for TraitRefKind {
1652 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1653 match self {
1654 TraitRefKind::SelfId => write!(f, "Self"),
1655 TraitRefKind::ParentClause(id, _decl_id, clause_id) => {
1656 let id = id.with_ctx(ctx);
1657 write!(f, "{id}::parent_clause{clause_id}")
1658 }
1659 TraitRefKind::ItemClause(id, _decl_id, type_name, clause_id) => {
1660 let id = id.with_ctx(ctx);
1661 let clause = clause_id.to_pretty_string();
1664 write!(f, "({id}::{type_name}::[{clause}])")
1665 }
1666 TraitRefKind::TraitImpl(impl_ref) => {
1667 write!(f, "{}", impl_ref.with_ctx(ctx))
1668 }
1669 TraitRefKind::Clause(id) => write!(f, "{}", id.with_ctx(ctx)),
1670 TraitRefKind::BuiltinOrAuto {
1671 trait_decl_ref: tr,
1672 types,
1673 ..
1674 } => {
1675 write!(f, "{}", tr.with_ctx(ctx))?;
1676 if !types.is_empty() {
1677 let types = types
1678 .iter()
1679 .map(|(name, ty, _)| {
1680 let ty = ty.with_ctx(ctx);
1681 format!("{name} = {ty}")
1682 })
1683 .join(", ");
1684 write!(f, " where {types}")?;
1685 }
1686 Ok(())
1687 }
1688 TraitRefKind::Dyn(tr) => write!(f, "{}", tr.with_ctx(ctx)),
1689 TraitRefKind::Unknown(msg) => write!(f, "UNKNOWN({msg})"),
1690 }
1691 }
1692}
1693
1694impl<C: AstFormatter> FmtWithCtx<C> for TraitRef {
1695 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1696 self.kind.fmt_with_ctx(ctx, f)
1697 }
1698}
1699
1700impl<C: AstFormatter> FmtWithCtx<C> for TraitTypeConstraint {
1701 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1702 let trait_ref = self.trait_ref.with_ctx(ctx);
1703 let ty = self.ty.with_ctx(ctx);
1704 write!(f, "{}::{} = {}", trait_ref, self.type_name, ty)
1705 }
1706}
1707
1708impl<C: AstFormatter> FmtWithCtx<C> for RegionBinder<(Vec<Ty>, Ty)> {
1709 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1710 let ctx = &ctx.push_bound_regions(&self.regions);
1712
1713 write!(f, "fn")?;
1714 if !self.regions.is_empty() {
1715 write!(
1716 f,
1717 "<{}>",
1718 self.regions.iter().map(|r| r.with_ctx(ctx)).format(", ")
1719 )?;
1720 }
1721 let (inputs, output) = &self.skip_binder;
1722 let inputs = inputs.iter().map(|x| x.with_ctx(ctx)).format(", ");
1723 write!(f, "({inputs})")?;
1724 if !output.is_unit() {
1725 let output = output.with_ctx(ctx);
1726 write!(f, " -> {output}")?;
1727 }
1728 Ok(())
1729 }
1730}
1731
1732impl<C: AstFormatter> FmtWithCtx<C> for Ty {
1733 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1734 match self.kind() {
1735 TyKind::Adt(tref) => {
1736 if tref.id.is_tuple() {
1737 assert!(tref.generics.trait_refs.is_empty());
1738 let generics = tref.generics.fmt_explicits(ctx).format(", ");
1739 write!(f, "({generics})")
1740 } else {
1741 write!(f, "{}", tref.with_ctx(ctx))
1742 }
1743 }
1744 TyKind::TypeVar(id) => write!(f, "{}", id.with_ctx(ctx)),
1745 TyKind::Literal(kind) => write!(f, "{kind}"),
1746 TyKind::Never => write!(f, "!"),
1747 TyKind::Ref(r, ty, kind) => {
1748 write!(f, "&{} ", r.with_ctx(ctx))?;
1749 if let RefKind::Mut = kind {
1750 write!(f, "mut ")?;
1751 }
1752 write!(f, "({})", ty.with_ctx(ctx))
1753 }
1754 TyKind::RawPtr(ty, kind) => {
1755 write!(f, "*")?;
1756 match kind {
1757 RefKind::Shared => write!(f, "const")?,
1758 RefKind::Mut => write!(f, "mut")?,
1759 }
1760 write!(f, " {}", ty.with_ctx(ctx))
1761 }
1762 TyKind::TraitType(trait_ref, name) => {
1763 write!(f, "{}::{name}", trait_ref.with_ctx(ctx),)
1764 }
1765 TyKind::DynTrait(pred) => {
1766 write!(f, "(dyn {})", pred.with_ctx(ctx))
1767 }
1768 TyKind::FnPtr(io) => {
1769 write!(f, "{}", io.with_ctx(ctx))
1770 }
1771 TyKind::FnDef(binder) => {
1772 let (regions, value) = binder.fmt_split(ctx);
1773 if !regions.is_empty() {
1774 write!(f, "for<{regions}> ",)?
1775 };
1776 write!(f, "{value}",)
1777 }
1778 TyKind::Error(msg) => write!(f, "type_error(\"{msg}\")"),
1779 }
1780 }
1781}
1782
1783impl<C: AstFormatter> FmtWithCtx<C> for TypeDbVar {
1784 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1785 ctx.format_bound_var(f, *self, "@Type", |v| Some(v.to_string()))
1786 }
1787}
1788
1789impl<C: AstFormatter> FmtWithCtx<C> for TypeDecl {
1790 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1791 let keyword = match &self.kind {
1792 TypeDeclKind::Struct(..) => "struct",
1793 TypeDeclKind::Union(..) => "union",
1794 TypeDeclKind::Enum(..) => "enum",
1795 TypeDeclKind::Alias(..) => "type",
1796 TypeDeclKind::Opaque | TypeDeclKind::Error(..) => "opaque type",
1797 };
1798 self.item_meta
1799 .fmt_item_intro(f, ctx, keyword, self.def_id)?;
1800
1801 let ctx = &ctx.set_generics(&self.generics);
1802 let (params, preds) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
1803 write!(f, "{params}{preds}")?;
1804
1805 let nl_or_space = if !self.generics.has_predicates() {
1806 " ".to_string()
1807 } else {
1808 "\n".to_string()
1809 };
1810 match &self.kind {
1811 TypeDeclKind::Struct(fields) => {
1812 write!(f, "{nl_or_space}{{")?;
1813 if !fields.is_empty() {
1814 writeln!(f)?;
1815 for field in fields {
1816 writeln!(f, " {},", field.with_ctx(ctx))?;
1817 }
1818 }
1819 write!(f, "}}")
1820 }
1821 TypeDeclKind::Union(fields) => {
1822 write!(f, "{nl_or_space}{{")?;
1823 writeln!(f)?;
1824 for field in fields {
1825 writeln!(f, " {},", field.with_ctx(ctx))?;
1826 }
1827 write!(f, "}}")
1828 }
1829 TypeDeclKind::Enum(variants) => {
1830 write!(f, "{nl_or_space}{{")?;
1831 writeln!(f)?;
1832 for variant in variants {
1833 writeln!(f, " {},", variant.with_ctx(ctx))?;
1834 }
1835 write!(f, "}}")
1836 }
1837 TypeDeclKind::Alias(ty) => write!(f, " = {}", ty.with_ctx(ctx)),
1838 TypeDeclKind::Opaque => write!(f, ""),
1839 TypeDeclKind::Error(msg) => write!(f, " = ERROR({msg})"),
1840 }
1841 }
1842}
1843
1844impl<C: AstFormatter> FmtWithCtx<C> for TypeDeclId {
1845 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1846 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
1847 }
1848}
1849
1850impl<C: AstFormatter> FmtWithCtx<C> for TypeDeclRef {
1851 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1852 let id = self.id.with_ctx(ctx);
1853 let generics = self.generics.with_ctx(ctx);
1854 write!(f, "{id}{generics}")
1855 }
1856}
1857
1858impl<C: AstFormatter> FmtWithCtx<C> for TypeId {
1859 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1860 match self {
1861 TypeId::Tuple => Ok(()),
1862 TypeId::Adt(def_id) => write!(f, "{}", def_id.with_ctx(ctx)),
1863 TypeId::Builtin(aty) => write!(f, "{}", aty.get_name().with_ctx(ctx)),
1864 }
1865 }
1866}
1867
1868impl_display_via_ctx!(TypeVar);
1869impl<C: AstFormatter> FmtWithCtx<C> for TypeVar {
1870 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1871 write!(f, "{}", self.name)
1872 }
1873}
1874
1875impl<C: AstFormatter> FmtWithCtx<C> for UnOp {
1876 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1877 match self {
1878 UnOp::Not => write!(f, "~"),
1879 UnOp::Neg(mode) => write!(f, "{}.-", mode),
1880 UnOp::PtrMetadata => write!(f, "ptr_metadata"),
1881 UnOp::Cast(kind) => write!(f, "{}", kind.with_ctx(ctx)),
1882 }
1883 }
1884}
1885
1886impl_display_via_ctx!(Variant);
1887impl<C: AstFormatter> FmtWithCtx<C> for Variant {
1888 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1889 write!(f, "{}", self.name)?;
1890 if !self.fields.is_empty() {
1891 let fields = self.fields.iter().map(|f| f.with_ctx(ctx)).format(", ");
1892 write!(f, "({})", fields)?;
1893 }
1894 Ok(())
1895 }
1896}