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