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