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