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