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