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