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