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