1use crate::{
3 common::{repeat_except_first, TAB_INCR},
4 formatter::*,
5 gast,
6 llbc_ast::{self as llbc, *},
7 reorder_decls::*,
8 ullbc_ast::{self as ullbc, *},
9};
10use either::Either;
11use itertools::Itertools;
12use std::{
13 borrow::Cow,
14 fmt::{self, Debug, Display},
15};
16
17pub struct WithCtx<'a, C, T: ?Sized> {
18 val: &'a T,
19 ctx: &'a C,
20}
21
22impl<'a, C, T: ?Sized> Display for WithCtx<'a, C, T>
23where
24 T: FmtWithCtx<C>,
25{
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 self.val.fmt_with_ctx(self.ctx, f)
28 }
29}
30
31pub trait FmtWithCtx<C> {
33 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result;
34
35 fn with_ctx<'a>(&'a self, ctx: &'a C) -> WithCtx<'a, C, Self> {
40 WithCtx { val: self, ctx }
41 }
42
43 fn to_string_with_ctx(&self, ctx: &C) -> String {
44 self.with_ctx(ctx).to_string()
45 }
46}
47
48macro_rules! impl_display_via_ctx {
49 ($ty:ty) => {
50 impl Display for $ty {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 self.fmt_with_ctx(&FmtCtx::new(), f)
53 }
54 }
55 };
56}
57macro_rules! impl_debug_via_display {
58 ($ty:ty) => {
59 impl Debug for $ty {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 <_ as Display>::fmt(self, f)
62 }
63 }
64 };
65}
66
67impl<C: AstFormatter> FmtWithCtx<C> for AbortKind {
70 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match self {
72 AbortKind::Panic(name) => {
73 write!(f, "panic")?;
74 if let Some(name) = name {
75 write!(f, "({})", name.with_ctx(ctx))?;
76 }
77 Ok(())
78 }
79 AbortKind::UndefinedBehavior => write!(f, "undefined_behavior"),
80 AbortKind::UnwindTerminate => write!(f, "unwind_terminate"),
81 }
82 }
83}
84
85impl<C: AstFormatter> FmtWithCtx<C> for AnyTransId {
86 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 match ctx
88 .get_crate()
89 .and_then(|translated| translated.item_short_name(*self))
90 {
91 None => write!(f, "{self}"),
92 Some(name) => name.fmt_with_ctx(ctx, f),
93 }
94 }
95}
96
97impl Display for AnyTransId {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
99 let s = match self {
100 AnyTransId::Type(x) => x.to_pretty_string(),
101 AnyTransId::Fun(x) => x.to_pretty_string(),
102 AnyTransId::Global(x) => x.to_pretty_string(),
103 AnyTransId::TraitDecl(x) => x.to_pretty_string(),
104 AnyTransId::TraitImpl(x) => x.to_pretty_string(),
105 };
106 f.write_str(&s)
107 }
108}
109
110impl<C: AstFormatter> FmtWithCtx<C> for AnyTransItem<'_> {
111 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 match self {
113 AnyTransItem::Type(d) => write!(f, "{}", d.with_ctx(ctx)),
114 AnyTransItem::Fun(d) => write!(f, "{}", d.with_ctx(ctx)),
115 AnyTransItem::Global(d) => write!(f, "{}", d.with_ctx(ctx)),
116 AnyTransItem::TraitDecl(d) => write!(f, "{}", d.with_ctx(ctx)),
117 AnyTransItem::TraitImpl(d) => write!(f, "{}", d.with_ctx(ctx)),
118 }
119 }
120}
121
122impl<C: AstFormatter> FmtWithCtx<C> for Assert {
123 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 write!(
125 f,
126 "assert({} == {})",
127 self.cond.with_ctx(ctx),
128 self.expected,
129 )
130 }
131}
132
133impl<T> Binder<T> {
134 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 let ctx = &ctx.push_binder(Cow::Borrowed(&self.params));
142 (
143 self.params.fmt_with_ctx_single_line(ctx),
144 self.skip_binder.to_string_with_ctx(ctx),
145 )
146 }
147}
148
149impl Display for BinOp {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
151 match self {
152 BinOp::BitXor => write!(f, "^"),
153 BinOp::BitAnd => write!(f, "&"),
154 BinOp::BitOr => write!(f, "|"),
155 BinOp::Eq => write!(f, "=="),
156 BinOp::Lt => write!(f, "<"),
157 BinOp::Le => write!(f, "<="),
158 BinOp::Ne => write!(f, "!="),
159 BinOp::Ge => write!(f, ">="),
160 BinOp::Gt => write!(f, ">"),
161 BinOp::Div => write!(f, "/"),
162 BinOp::Rem => write!(f, "%"),
163 BinOp::Add => write!(f, "+"),
164 BinOp::Sub => write!(f, "-"),
165 BinOp::Mul => write!(f, "*"),
166 BinOp::WrappingAdd => write!(f, "wrapping.+"),
167 BinOp::WrappingSub => write!(f, "wrapping.-"),
168 BinOp::WrappingMul => write!(f, "wrapping.*"),
169 BinOp::CheckedAdd => write!(f, "checked.+"),
170 BinOp::CheckedSub => write!(f, "checked.-"),
171 BinOp::CheckedMul => write!(f, "checked.*"),
172 BinOp::Shl => write!(f, "<<"),
173 BinOp::Shr => write!(f, ">>"),
174 BinOp::Cmp => write!(f, "cmp"),
175 BinOp::Offset => write!(f, "offset"),
176 }
177 }
178}
179
180impl<C: AstFormatter> FmtWithCtx<C> for llbc::Block {
181 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 for st in &self.statements {
183 writeln!(f, "{}", st.with_ctx(ctx))?;
184 }
185 Ok(())
186 }
187}
188
189impl<C: AstFormatter> FmtWithCtx<C> for ullbc::BlockData {
190 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 for statement in &self.statements {
192 writeln!(f, "{};", statement.with_ctx(ctx))?;
193 }
194 write!(f, "{};", self.terminator.with_ctx(ctx))?;
195 Ok(())
196 }
197}
198
199impl<C: AstFormatter> FmtWithCtx<C> for gast::Body {
200 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 match self {
202 Body::Unstructured(b) => write!(f, "{}", b.with_ctx(ctx)),
203 Body::Structured(b) => write!(f, "{}", b.with_ctx(ctx)),
204 }
205 }
206}
207
208impl Display for BorrowKind {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
210 write!(f, "{self:?}")
212 }
213}
214
215impl Display for BuiltinFunId {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
217 let name = match *self {
218 BuiltinFunId::BoxNew => "BoxNew",
219 BuiltinFunId::ArrayToSliceShared => "ArrayToSliceShared",
220 BuiltinFunId::ArrayToSliceMut => "ArrayToSliceMut",
221 BuiltinFunId::ArrayRepeat => "ArrayRepeat",
222 BuiltinFunId::Index(BuiltinIndexOp {
223 is_array,
224 mutability,
225 is_range,
226 }) => {
227 let ty = if is_array { "Array" } else { "Slice" };
228 let op = if is_range { "SubSlice" } else { "Index" };
229 let mutability = mutability.variant_name();
230 &format!("{ty}{op}{mutability}")
231 }
232 BuiltinFunId::PtrFromParts(mutability) => {
233 let mutability = mutability.variant_name();
234 &format!("PtrFromParts{mutability}")
235 }
236 };
237 f.write_str(name)
238 }
239}
240
241impl<C: AstFormatter> FmtWithCtx<C> for Call {
242 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 let dest = self.dest.with_ctx(ctx);
244 let func = self.func.with_ctx(ctx);
245 let args = self.args.iter().map(|x| x.with_ctx(ctx)).format(", ");
246 write!(f, "{dest} := {func}({args})")
247 }
248}
249
250impl<C: AstFormatter> FmtWithCtx<C> for CastKind {
251 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252 match self {
253 CastKind::Scalar(src, tgt) => write!(f, "cast<{src}, {tgt}>"),
254 CastKind::FnPtr(src, tgt) | CastKind::RawPtr(src, tgt) => {
255 write!(f, "cast<{}, {}>", src.with_ctx(ctx), tgt.with_ctx(ctx))
256 }
257 CastKind::Unsize(src, tgt) => {
258 write!(
259 f,
260 "unsize_cast<{}, {}>",
261 src.with_ctx(ctx),
262 tgt.with_ctx(ctx)
263 )
264 }
265 CastKind::Transmute(src, tgt) => {
266 write!(f, "transmute<{}, {}>", src.with_ctx(ctx), tgt.with_ctx(ctx))
267 }
268 }
269 }
270}
271
272impl<C: AstFormatter> FmtWithCtx<C> for ClauseDbVar {
273 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 ctx.format_bound_var(f, *self, "@TraitClause", |_| None)
275 }
276}
277
278impl_display_via_ctx!(ConstantExpr);
279impl<C: AstFormatter> FmtWithCtx<C> for ConstantExpr {
280 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 write!(f, "{}", self.value.with_ctx(ctx))
282 }
283}
284
285impl<C: AstFormatter> FmtWithCtx<C> for ConstGeneric {
286 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287 match self {
288 ConstGeneric::Var(id) => write!(f, "{}", id.with_ctx(ctx)),
289 ConstGeneric::Value(v) => write!(f, "{v}"),
290 ConstGeneric::Global(id) => write!(f, "{}", id.with_ctx(ctx)),
291 }
292 }
293}
294
295impl<C: AstFormatter> FmtWithCtx<C> for ConstGenericDbVar {
296 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
297 ctx.format_bound_var(f, *self, "@ConstGeneric", |v| Some(v.to_string()))
298 }
299}
300
301impl_display_via_ctx!(ConstGenericVar);
302impl<C: AstFormatter> FmtWithCtx<C> for ConstGenericVar {
303 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 write!(f, "const {} : {}", self.name, self.ty)
305 }
306}
307
308impl Display for DeBruijnId {
309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
310 write!(f, "{}", self.index)
311 }
312}
313
314impl<Id: Display> Display for DeBruijnVar<Id> {
315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316 match self {
317 Self::Bound(dbid, varid) => write!(f, "{dbid}_{varid}"),
318 Self::Free(varid) => write!(f, "{varid}"),
319 }
320 }
321}
322
323impl<C: AstFormatter> FmtWithCtx<C> for DeclarationGroup {
324 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
325 use DeclarationGroup::*;
326 match self {
327 Type(g) => write!(f, "Type decls group: {}", g.with_ctx(ctx)),
328 Fun(g) => write!(f, "Fun decls group: {}", g.with_ctx(ctx)),
329 Global(g) => write!(f, "Global decls group: {}", g.with_ctx(ctx)),
330 TraitDecl(g) => write!(f, "Trait decls group: {}", g.with_ctx(ctx)),
331 TraitImpl(g) => write!(f, "Trait impls group: {}", g.with_ctx(ctx)),
332 Mixed(g) => write!(f, "Mixed group: {}", g.with_ctx(ctx)),
333 }
334 }
335}
336
337impl<C: AstFormatter> FmtWithCtx<C> for ExistentialPredicate {
338 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339 write!(f, "exists(TODO)")
340 }
341}
342
343impl_display_via_ctx!(Field);
344impl<C: AstFormatter> FmtWithCtx<C> for Field {
345 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346 if let Some(name) = &self.name {
347 write!(f, "{}: ", name)?
348 }
349 write!(f, "{}", self.ty.with_ctx(ctx))
350 }
351}
352
353impl Display for FileName {
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
355 match self {
356 FileName::Virtual(path_buf) | FileName::Local(path_buf) => {
357 write!(f, "{}", path_buf.display())
358 }
359 FileName::NotReal(name) => write!(f, "{}", name),
360 }
361 }
362}
363
364impl Display for FloatTy {
365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
366 match self {
367 FloatTy::F16 => write!(f, "f16"),
368 FloatTy::F32 => write!(f, "f32"),
369 FloatTy::F64 => write!(f, "f64"),
370 FloatTy::F128 => write!(f, "f128"),
371 }
372 }
373}
374
375impl Display for FloatValue {
376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
377 let v = &self.value;
378 match self.ty {
379 FloatTy::F16 => write!(f, "{v} : f16"),
380 FloatTy::F32 => write!(f, "{v} : f32"),
381 FloatTy::F64 => write!(f, "{v} : f64"),
382 FloatTy::F128 => write!(f, "{v} : f128"),
383 }
384 }
385}
386
387impl<C: AstFormatter> FmtWithCtx<C> for FnOperand {
388 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389 match self {
390 FnOperand::Regular(func) => write!(f, "{}", func.with_ctx(ctx)),
391 FnOperand::Move(p) => write!(f, "(move {})", p.with_ctx(ctx)),
392 }
393 }
394}
395
396impl<C: AstFormatter> FmtWithCtx<C> for FnPtr {
397 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
398 match self.func.as_ref() {
399 FunIdOrTraitMethodRef::Fun(FunId::Regular(def_id)) => {
400 write!(f, "{}", def_id.with_ctx(ctx))?
401 }
402 FunIdOrTraitMethodRef::Fun(FunId::Builtin(builtin)) => write!(f, "@{}", builtin)?,
403 FunIdOrTraitMethodRef::Trait(trait_ref, method_id, _) => {
404 write!(f, "{}::{}", trait_ref.with_ctx(ctx), &method_id.0)?
405 }
406 };
407 write!(f, "{}", self.generics.with_ctx(ctx))
408 }
409}
410
411impl<C: AstFormatter> FmtWithCtx<C> for FunDecl {
412 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413 let keyword = if self.signature.is_unsafe {
414 "unsafe fn"
415 } else {
416 "fn"
417 };
418 self.item_meta
419 .fmt_item_intro(f, ctx, keyword, self.def_id)?;
420
421 let ctx = &ctx.set_generics(&self.signature.generics);
423
424 let (params, preds) = self.signature.generics.fmt_with_ctx_with_trait_clauses(ctx);
426 write!(f, "{params}")?;
427
428 let mut args: Vec<String> = Vec::new();
430 for (i, ty) in self.signature.inputs.iter().enumerate() {
431 let id = LocalId::new(i + 1);
434 args.push(format!("{}: {}", id.to_pretty_string(), ty.with_ctx(ctx)));
435 }
436 let args = args.join(", ");
437 write!(f, "({args})")?;
438
439 if !self.signature.output.is_unit() {
441 write!(f, " -> {}", self.signature.output.with_ctx(ctx))?;
442 };
443 write!(f, "{preds}")?;
444
445 match &self.body {
447 Ok(body) => {
448 let tab = ctx.indent();
449 let body = body.with_ctx(ctx);
450 write!(f, "\n{tab}{{\n{body}{tab}}}")?;
451 }
452 Err(Opaque) => {}
453 }
454
455 Ok(())
456 }
457}
458
459impl<C: AstFormatter> FmtWithCtx<C> for FunDeclId {
460 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
461 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
462 }
463}
464
465impl<C: AstFormatter> FmtWithCtx<C> for FunDeclRef {
466 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467 let id = self.id.with_ctx(ctx);
468 let generics = self.generics.with_ctx(ctx);
469 write!(f, "{id}{generics}")
470 }
471}
472
473impl<C: AstFormatter> FmtWithCtx<C> for FunSig {
474 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475 let ctx = &ctx.set_generics(&self.generics);
476
477 if self.is_unsafe {
479 write!(f, "unsafe ")?;
480 }
481
482 let (params, clauses) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
484 write!(f, "fn{params}")?;
485
486 let args = self
488 .inputs
489 .iter()
490 .map(|ty| ty.with_ctx(ctx).to_string())
491 .format(", ");
492 write!(f, "({args})")?;
493
494 if !self.output.is_unit() {
496 write!(f, " -> {}", self.output.with_ctx(ctx))?;
497 }
498
499 write!(f, "{clauses}")?;
500 Ok(())
501 }
502}
503
504impl<Id: Copy, C: AstFormatter> FmtWithCtx<C> for GDeclarationGroup<Id>
505where
506 Id: FmtWithCtx<C>,
507{
508 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509 use GDeclarationGroup::*;
510 match self {
511 NonRec(id) => write!(f, "Non rec: {}", id.with_ctx(ctx)),
512 Rec(ids) => {
513 let ids = ids.iter().map(|id| id.with_ctx(ctx)).format(", ");
514 write!(f, "Rec: {}", ids)
515 }
516 }
517 }
518}
519
520impl GenericArgs {
521 pub(crate) fn fmt_explicits<'a, C: AstFormatter>(
522 &'a self,
523 ctx: &'a C,
524 ) -> impl Iterator<Item = impl Display + 'a> {
525 let regions = self.regions.iter().map(|x| x.with_ctx(ctx));
526 let types = self.types.iter().map(|x| x.with_ctx(ctx));
527 let const_generics = self.const_generics.iter().map(|x| x.with_ctx(ctx));
528 regions.map(Either::Left).chain(
529 types
530 .map(Either::Left)
531 .chain(const_generics.map(Either::Right))
532 .map(Either::Right),
533 )
534 }
535
536 pub(crate) fn fmt_implicits<'a, C: AstFormatter>(
537 &'a self,
538 ctx: &'a C,
539 ) -> impl Iterator<Item = impl Display + 'a> {
540 self.trait_refs.iter().map(|x| x.with_ctx(ctx))
541 }
542}
543
544impl_display_via_ctx!(GenericArgs);
545impl_debug_via_display!(GenericArgs);
546impl<C: AstFormatter> FmtWithCtx<C> for GenericArgs {
547 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
548 if self.has_explicits() {
549 write!(f, "<{}>", self.fmt_explicits(ctx).format(", "))?;
550 }
551 if self.has_implicits() {
552 write!(f, "[{}]", self.fmt_implicits(ctx).format(", "))?;
553 }
554 Ok(())
555 }
556}
557
558impl GenericParams {
559 fn formatted_params<'a, C>(&'a self, ctx: &'a C) -> impl Iterator<Item = impl Display + 'a>
560 where
561 C: AstFormatter,
562 {
563 let regions = self.regions.iter().map(|x| x.with_ctx(ctx));
564 let types = self.types.iter();
565 let const_generics = self.const_generics.iter();
566 regions.map(Either::Left).chain(
567 types
568 .map(Either::Left)
569 .chain(const_generics.map(Either::Right))
570 .map(Either::Right),
571 )
572 }
573
574 fn formatted_clauses<'a, C>(&'a self, ctx: &'a C) -> impl Iterator<Item = impl Display + 'a>
575 where
576 C: AstFormatter,
577 {
578 let trait_clauses = self.trait_clauses.iter().map(|x| x.to_string_with_ctx(ctx));
579 let types_outlive = self.types_outlive.iter().map(|x| x.fmt_as_for(ctx));
580 let regions_outlive = self.regions_outlive.iter().map(|x| x.fmt_as_for(ctx));
581 let type_constraints = self
582 .trait_type_constraints
583 .iter()
584 .map(|x| x.fmt_as_for(ctx));
585 trait_clauses.map(Either::Left).chain(
586 types_outlive
587 .chain(regions_outlive)
588 .chain(type_constraints)
589 .map(Either::Right),
590 )
591 }
592
593 pub fn fmt_with_ctx_with_trait_clauses<C>(&self, ctx: &C) -> (String, String)
594 where
595 C: AstFormatter,
596 {
597 let tab = ctx.indent();
598 let params = if self.has_explicits() {
599 let params = self.formatted_params(ctx).format(", ");
600 format!("<{}>", params)
601 } else {
602 String::new()
603 };
604 let clauses = if self.has_predicates() {
605 let clauses = self
606 .formatted_clauses(ctx)
607 .map(|x| format!("\n{tab}{TAB_INCR}{x},"))
608 .format("");
609 format!("\n{tab}where{clauses}")
610 } else {
611 String::new()
612 };
613 (params, clauses)
614 }
615
616 pub fn fmt_with_ctx_single_line<C>(&self, ctx: &C) -> String
617 where
618 C: AstFormatter,
619 {
620 if self.is_empty() {
621 String::new()
622 } else {
623 let params = self
624 .formatted_params(ctx)
625 .map(Either::Left)
626 .chain(self.formatted_clauses(ctx).map(Either::Right))
627 .format(", ");
628 format!("<{}>", params)
629 }
630 }
631}
632
633impl_debug_via_display!(GenericParams);
634impl Display for GenericParams {
635 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
636 write!(f, "{}", self.fmt_with_ctx_single_line(&FmtCtx::new()))
637 }
638}
639
640impl<C: AstFormatter> FmtWithCtx<C> for GenericsSource {
641 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
642 match self {
643 GenericsSource::Item(id) => write!(f, "{}", id.with_ctx(ctx)),
644 GenericsSource::Method(id, name) => write!(f, "{}::{name}", id.with_ctx(ctx)),
645 GenericsSource::Builtin => write!(f, "<builtin>"),
646 GenericsSource::Other => write!(f, "<unknown>"),
647 }
648 }
649}
650
651impl<T> GExprBody<T> {
652 fn fmt_with_ctx_and_callback<C: AstFormatter>(
653 &self,
654 ctx: &C,
655 f: &mut fmt::Formatter<'_>,
656 fmt_body: impl for<'a, 'b> FnOnce(
657 &mut fmt::Formatter<'_>,
658 &<C::Reborrow<'b> as AstFormatter>::Reborrow<'a>,
659 &'a T,
660 ) -> fmt::Result,
661 ) -> fmt::Result {
662 let ctx = &ctx.set_locals(&self.locals);
664 let ctx = &ctx.increase_indent();
665 let tab = ctx.indent();
666
667 for v in &self.locals.locals {
669 write!(f, "{tab}")?;
670 write!(f, "let {v}: {};", v.ty.with_ctx(ctx))?;
671
672 write!(f, " // ")?;
673 let index = v.index.index();
674 if index == 0 {
675 write!(f, "return")?;
676 } else if index <= self.locals.arg_count {
677 write!(f, "arg #{index}")?
678 } else {
679 match &v.name {
680 Some(_) => write!(f, "local")?,
681 None => write!(f, "anonymous local")?,
682 }
683 }
684 writeln!(f)?;
685 }
686
687 fmt_body(f, ctx, &self.body)?;
688
689 Ok(())
690 }
691}
692
693impl<C: AstFormatter> FmtWithCtx<C> for GExprBody<llbc_ast::Block> {
694 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
695 self.fmt_with_ctx_and_callback(ctx, f, |f, ctx, body| {
696 writeln!(f)?;
697 body.fmt_with_ctx(ctx, f)?;
698 Ok(())
699 })
700 }
701}
702impl<C: AstFormatter> FmtWithCtx<C> for GExprBody<ullbc_ast::BodyContents> {
703 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
704 self.fmt_with_ctx_and_callback(ctx, f, |f, ctx, body| {
705 let tab = ctx.indent();
706 let ctx = &ctx.increase_indent();
707 for (bid, block) in body.iter_indexed_values() {
708 writeln!(f)?;
709 writeln!(f, "{tab}bb{}: {{", bid.index())?;
710 writeln!(f, "{}", block.with_ctx(ctx))?;
711 writeln!(f, "{tab}}}")?;
712 }
713 Ok(())
714 })
715 }
716}
717
718impl<C> FmtWithCtx<C> for GlobalDecl
719where
720 C: AstFormatter,
721{
722 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
723 let keyword = match self.global_kind {
724 GlobalKind::Static => "static",
725 GlobalKind::AnonConst | GlobalKind::NamedConst => "const",
726 };
727 self.item_meta
728 .fmt_item_intro(f, ctx, keyword, self.def_id)?;
729
730 let ctx = &ctx.set_generics(&self.generics);
732
733 let (params, preds) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
735
736 let ty = self.ty.with_ctx(ctx);
738 write!(f, "{params}: {ty}")?;
739
740 write!(f, "{preds}")?;
742 if self.generics.has_predicates() {
743 write!(f, "\n")?;
744 }
745 write!(f, " ")?;
746
747 let initializer = self.init.with_ctx(ctx);
749 write!(f, "= {initializer}()")?;
750
751 Ok(())
752 }
753}
754
755impl<C: AstFormatter> FmtWithCtx<C> for GlobalDeclId {
756 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
757 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
758 }
759}
760
761impl<C: AstFormatter> FmtWithCtx<C> for GlobalDeclRef {
762 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
763 let id = self.id.with_ctx(ctx);
764 let generics = self.generics.with_ctx(ctx);
765 write!(f, "{id}{generics}")
766 }
767}
768
769impl<C: AstFormatter> FmtWithCtx<C> for ImplElem {
770 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
771 write!(f, "{{")?;
772 match self {
773 ImplElem::Ty(bound_ty) => {
774 let ctx = ctx.set_generics(&bound_ty.params);
776 bound_ty.skip_binder.fmt_with_ctx(&ctx, f)?
777 }
778 ImplElem::Trait(impl_id) => {
779 match ctx.get_crate().and_then(|tr| tr.trait_impls.get(*impl_id)) {
780 None => write!(f, "impl#{impl_id}")?,
781 Some(timpl) => {
782 let ctx = &ctx.set_generics(&timpl.generics);
785 let mut impl_trait = timpl.impl_trait.clone();
786 let self_ty = impl_trait.generics.types.remove(TypeVarId::ZERO).unwrap();
787 write!(
788 f,
789 "impl {} for {}",
790 impl_trait.with_ctx(ctx),
791 self_ty.with_ctx(ctx)
792 )?;
793 }
794 }
795 }
796 }
797 write!(f, "}}")
798 }
799}
800
801impl Display for IntegerTy {
802 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
803 match self {
804 IntegerTy::Isize => write!(f, "isize"),
805 IntegerTy::I8 => write!(f, "i8"),
806 IntegerTy::I16 => write!(f, "i16"),
807 IntegerTy::I32 => write!(f, "i32"),
808 IntegerTy::I64 => write!(f, "i64"),
809 IntegerTy::I128 => write!(f, "i128"),
810 IntegerTy::Usize => write!(f, "usize"),
811 IntegerTy::U8 => write!(f, "u8"),
812 IntegerTy::U16 => write!(f, "u16"),
813 IntegerTy::U32 => write!(f, "u32"),
814 IntegerTy::U64 => write!(f, "u64"),
815 IntegerTy::U128 => write!(f, "u128"),
816 }
817 }
818}
819
820impl ItemMeta {
821 pub fn fmt_item_intro<C: AstFormatter>(
823 &self,
824 f: &mut fmt::Formatter<'_>,
825 ctx: &C,
826 keyword: &str,
827 id: impl Into<AnyTransId>,
828 ) -> fmt::Result {
829 let tab = ctx.indent();
830 let full_name = self.name.with_ctx(ctx);
831 let name = if let Some(tr) = ctx.get_crate()
832 && let Some(short_name) = tr.short_names.get(&id.into())
833 {
834 writeln!(f, "// Full name: {full_name}")?;
835 short_name.with_ctx(ctx)
836 } else {
837 full_name
838 };
839 if let Some(id) = &self.lang_item {
840 writeln!(f, "{tab}#[lang_item(\"{id}\")]")?;
841 }
842 write!(f, "{tab}")?;
843 if self.attr_info.public {
844 write!(f, "pub ")?;
845 }
846 write!(f, "{keyword} {name}")
847 }
848}
849
850impl Display for Literal {
851 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
852 match self {
853 Literal::Scalar(v) => write!(f, "{v}"),
854 Literal::Float(v) => write!(f, "{v}"),
855 Literal::Bool(v) => write!(f, "{v}"),
856 Literal::Char(v) => write!(f, "{v}"),
857 Literal::Str(v) => write!(f, "\"{}\"", v.replace("\\", "\\\\").replace("\n", "\\n")),
858 Literal::ByteStr(v) => write!(f, "{v:?}"),
859 }
860 }
861}
862
863impl Display for LiteralTy {
864 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
865 match self {
866 LiteralTy::Integer(ty) => write!(f, "{ty}"),
867 LiteralTy::Float(ty) => write!(f, "{ty}"),
868 LiteralTy::Char => write!(f, "char"),
869 LiteralTy::Bool => write!(f, "bool"),
870 }
871 }
872}
873
874impl Display for Loc {
875 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
876 write!(f, "{}:{}", self.line, self.col)
877 }
878}
879
880impl Display for Local {
881 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
882 if let Some(name) = &self.name {
885 write!(f, "{name}")?
886 }
887 write!(f, "{}", self.index.to_pretty_string())?;
888 Ok(())
889 }
890}
891
892impl<C: AstFormatter> FmtWithCtx<C> for LocalId {
893 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
894 ctx.format_local_id(f, *self)
895 }
896}
897
898impl<C: AstFormatter> FmtWithCtx<C> for Name {
899 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
900 let name = self.name.iter().map(|x| x.with_ctx(ctx)).format("::");
901 write!(f, "{}", name)
902 }
903}
904
905impl<C: AstFormatter> FmtWithCtx<C> for NullOp {
906 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
907 let op = match self {
908 NullOp::SizeOf => "size_of",
909 NullOp::AlignOf => "align_of",
910 NullOp::OffsetOf(_) => "offset_of(?)",
911 NullOp::UbChecks => "ub_checks",
912 };
913 write!(f, "{op}")
914 }
915}
916
917impl_display_via_ctx!(Operand);
918impl<C: AstFormatter> FmtWithCtx<C> for Operand {
919 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
920 match self {
921 Operand::Copy(p) => write!(f, "copy ({})", p.with_ctx(ctx)),
922 Operand::Move(p) => write!(f, "move ({})", p.with_ctx(ctx)),
923 Operand::Const(c) => write!(f, "const ({})", c.with_ctx(ctx)),
924 }
925 }
926}
927
928impl<C: AstFormatter, T, U> FmtWithCtx<C> for OutlivesPred<T, U>
929where
930 T: FmtWithCtx<C>,
931 U: FmtWithCtx<C>,
932{
933 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
934 write!(f, "{} : {}", self.0.with_ctx(ctx), self.1.with_ctx(ctx))
935 }
936}
937
938impl<C: AstFormatter> FmtWithCtx<C> for PathElem {
939 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
940 match self {
941 PathElem::Ident(s, d) => {
942 write!(f, "{s}")?;
943 if !d.is_zero() {
944 write!(f, "#{}", d)?;
945 }
946 Ok(())
947 }
948 PathElem::Impl(impl_elem, d) => {
949 write!(f, "{}", impl_elem.with_ctx(ctx))?;
950 if !d.is_zero() {
951 write!(f, "#{}", d)?;
952 }
953 Ok(())
954 }
955 PathElem::Monomorphized(args) => {
956 write!(f, "<{}>", args.fmt_explicits(ctx).format(", "))
957 }
958 }
959 }
960}
961
962impl_display_via_ctx!(Place);
963impl<C: AstFormatter> FmtWithCtx<C> for Place {
964 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
965 match &self.kind {
966 PlaceKind::Local(var_id) => write!(f, "{}", var_id.with_ctx(ctx)),
967 PlaceKind::Projection(subplace, projection) => {
968 let sub = subplace.with_ctx(ctx);
969 match projection {
970 ProjectionElem::Deref => {
971 write!(f, "*({sub})")
972 }
973 ProjectionElem::Field(proj_kind, field_id) => match proj_kind {
974 FieldProjKind::Adt(adt_id, opt_variant_id) => {
975 write!(f, "({sub}")?;
976 if let Some(variant_id) = opt_variant_id {
977 write!(f, " as variant @{variant_id}")?
978 }
979 write!(f, ").")?;
980 ctx.format_field_name(f, *adt_id, *opt_variant_id, *field_id)?;
981 Ok(())
982 }
983 FieldProjKind::Tuple(_) => {
984 write!(f, "({sub}).{field_id}")
985 }
986 },
987 ProjectionElem::Index {
988 offset,
989 from_end: true,
990 ..
991 } => write!(f, "({sub})[-{}]", offset.with_ctx(ctx)),
992 ProjectionElem::Index {
993 offset,
994 from_end: false,
995 ..
996 } => write!(f, "({sub})[{}]", offset.with_ctx(ctx)),
997 ProjectionElem::Subslice {
998 from,
999 to,
1000 from_end: true,
1001 ..
1002 } => write!(f, "({sub})[{}..-{}]", from.with_ctx(ctx), to.with_ctx(ctx)),
1003 ProjectionElem::Subslice {
1004 from,
1005 to,
1006 from_end: false,
1007 ..
1008 } => write!(f, "({sub})[{}..{}]", from.with_ctx(ctx), to.with_ctx(ctx)),
1009 }
1010 }
1011 }
1012 }
1013}
1014
1015impl<C: AstFormatter> FmtWithCtx<C> for PolyTraitDeclRef {
1016 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1017 write!(f, "{}", self.fmt_as_for(ctx))
1018 }
1019}
1020
1021impl Display for RawAttribute {
1022 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1023 write!(f, "{}", self.path)?;
1024 if let Some(args) = &self.args {
1025 write!(f, "({args})")?;
1026 }
1027 Ok(())
1028 }
1029}
1030
1031impl<C: AstFormatter> FmtWithCtx<C> for RawConstantExpr {
1032 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1033 match self {
1034 RawConstantExpr::Literal(c) => write!(f, "{}", c.to_string()),
1035 RawConstantExpr::Adt(variant_id, values) => {
1036 let variant_id = match variant_id {
1040 Some(id) => format!("Some({id})"),
1041 None => "None".to_string(),
1042 };
1043 let values = values.iter().map(|v| v.with_ctx(ctx)).format(", ");
1044 write!(f, "ConstAdt {} [{}]", variant_id, values)
1045 }
1046 RawConstantExpr::Array(values) => {
1047 let values = values.iter().map(|v| v.with_ctx(ctx)).format(", ");
1048 write!(f, "[{}]", values)
1049 }
1050 RawConstantExpr::Global(global_ref) => {
1051 write!(f, "{}", global_ref.with_ctx(ctx))
1052 }
1053 RawConstantExpr::TraitConst(trait_ref, name) => {
1054 write!(f, "{}::{name}", trait_ref.with_ctx(ctx),)
1055 }
1056 RawConstantExpr::Ref(cv) => {
1057 write!(f, "&{}", cv.with_ctx(ctx))
1058 }
1059 RawConstantExpr::MutPtr(cv) => {
1060 write!(f, "&raw mut {}", cv.with_ctx(ctx))
1061 }
1062 RawConstantExpr::Var(id) => write!(f, "{}", id.with_ctx(ctx)),
1063 RawConstantExpr::FnPtr(fp) => {
1064 write!(f, "{}", fp.with_ctx(ctx))
1065 }
1066 RawConstantExpr::RawMemory(bytes) => write!(f, "RawMemory({bytes:?})"),
1067 RawConstantExpr::Opaque(cause) => write!(f, "Opaque({cause})"),
1068 }
1069 }
1070}
1071
1072impl<C: AstFormatter> FmtWithCtx<C> for Region {
1073 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1074 match self {
1075 Region::Static => write!(f, "'static"),
1076 Region::Var(var) => write!(f, "{}", var.with_ctx(ctx)),
1077 Region::Erased => write!(f, "'_"),
1078 }
1079 }
1080}
1081
1082impl<T> RegionBinder<T> {
1083 fn fmt_split<'a, C>(&'a self, ctx: &'a C) -> (String, String)
1085 where
1086 C: AstFormatter,
1087 T: FmtWithCtx<C::Reborrow<'a>>,
1088 {
1089 let ctx = &ctx.push_bound_regions(&self.regions);
1090 (
1091 self.regions
1092 .iter()
1093 .map(|r| r.with_ctx(ctx))
1094 .format(", ")
1095 .to_string(),
1096 self.skip_binder.to_string_with_ctx(ctx),
1097 )
1098 }
1099
1100 fn fmt_as_for<'a, C>(&'a self, ctx: &'a C) -> String
1102 where
1103 C: AstFormatter,
1104 T: FmtWithCtx<C::Reborrow<'a>>,
1105 {
1106 let (regions, value) = self.fmt_split(ctx);
1107 let regions = if regions.is_empty() {
1108 "".to_string()
1109 } else {
1110 format!("for<{regions}> ",)
1111 };
1112 format!("{regions}{value}",)
1113 }
1114}
1115
1116impl<C: AstFormatter> FmtWithCtx<C> for RegionDbVar {
1117 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1118 ctx.format_bound_var(f, *self, "'_", |v| {
1119 v.name.as_ref().map(|name| name.to_string())
1120 })
1121 }
1122}
1123
1124impl_display_via_ctx!(RegionVar);
1125impl<C: AstFormatter> FmtWithCtx<C> for RegionVar {
1126 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1127 match &self.name {
1128 Some(name) => write!(f, "{name}"),
1129 None => write!(f, "'_{}", self.index),
1130 }
1131 }
1132}
1133
1134impl_display_via_ctx!(Rvalue);
1135impl<C: AstFormatter> FmtWithCtx<C> for Rvalue {
1136 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1137 match self {
1138 Rvalue::Use(x) => write!(f, "{}", x.with_ctx(ctx)),
1139 Rvalue::Ref(place, borrow_kind) => {
1140 let borrow_kind = match borrow_kind {
1141 BorrowKind::Shared => "&",
1142 BorrowKind::Mut => "&mut ",
1143 BorrowKind::TwoPhaseMut => "&two-phase-mut ",
1144 BorrowKind::UniqueImmutable => "&uniq ",
1145 BorrowKind::Shallow => "&shallow ",
1146 };
1147 write!(f, "{borrow_kind}{}", place.with_ctx(ctx))
1148 }
1149 Rvalue::RawPtr(place, mutability) => {
1150 let ptr_kind = match mutability {
1151 RefKind::Shared => "&raw const ",
1152 RefKind::Mut => "&raw mut ",
1153 };
1154 write!(f, "{ptr_kind}{}", place.with_ctx(ctx))
1155 }
1156
1157 Rvalue::BinaryOp(binop, x, y) => {
1158 write!(f, "{} {} {}", x.with_ctx(ctx), binop, y.with_ctx(ctx))
1159 }
1160 Rvalue::UnaryOp(unop, x) => {
1161 write!(f, "{}({})", unop.with_ctx(ctx), x.with_ctx(ctx))
1162 }
1163 Rvalue::NullaryOp(op, ty) => {
1164 write!(f, "{}<{}>", op.with_ctx(ctx), ty.with_ctx(ctx))
1165 }
1166 Rvalue::Discriminant(p, _) => {
1167 write!(f, "@discriminant({})", p.with_ctx(ctx),)
1168 }
1169 Rvalue::Aggregate(kind, ops) => {
1170 let ops_s = ops.iter().map(|op| op.with_ctx(ctx)).format(", ");
1171 match kind {
1172 AggregateKind::Adt(def_id, variant_id, field_id, _) => {
1173 match def_id {
1174 TypeId::Tuple => write!(f, "({})", ops_s),
1175 TypeId::Builtin(_) => unreachable!(),
1176 TypeId::Adt(def_id) => {
1177 match variant_id {
1178 None => def_id.fmt_with_ctx(ctx, f)?,
1179 Some(variant_id) => {
1180 ctx.format_enum_variant(f, *def_id, *variant_id)?
1181 }
1182 }
1183 write!(f, " {{ ")?;
1184 for (comma, (i, op)) in
1185 repeat_except_first(", ").zip(ops.iter().enumerate())
1186 {
1187 write!(f, "{}", comma.unwrap_or_default())?;
1188 let field_id = match *field_id {
1189 None => FieldId::new(i),
1190 Some(field_id) => {
1191 assert_eq!(i, 0); field_id
1193 }
1194 };
1195 ctx.format_field_name(f, *def_id, *variant_id, field_id)?;
1196 write!(f, ": {}", op.with_ctx(ctx))?;
1197 }
1198 write!(f, " }}")
1199 }
1200 }
1201 }
1202 AggregateKind::Array(..) => {
1203 write!(f, "[{}]", ops_s)
1204 }
1205 AggregateKind::RawPtr(_, rmut) => {
1206 let mutability = match rmut {
1207 RefKind::Shared => "const",
1208 RefKind::Mut => "mut ",
1209 };
1210 write!(f, "*{} ({})", mutability, ops_s)
1211 }
1212 }
1213 }
1214 Rvalue::Global(global_ref) => write!(f, "{}", global_ref.with_ctx(ctx)),
1215 Rvalue::GlobalRef(global_ref, RefKind::Shared) => {
1216 write!(f, "&{}", global_ref.with_ctx(ctx))
1217 }
1218 Rvalue::GlobalRef(global_ref, RefKind::Mut) => {
1219 write!(f, "&raw mut {}", global_ref.with_ctx(ctx))
1220 }
1221 Rvalue::Len(place, ..) => write!(f, "len({})", place.with_ctx(ctx)),
1222 Rvalue::Repeat(op, _ty, cg) => {
1223 write!(f, "[{}; {}]", op.with_ctx(ctx), cg.with_ctx(ctx))
1224 }
1225 Rvalue::ShallowInitBox(op, ty) => {
1226 write!(
1227 f,
1228 "shallow_init_box::<{}>({})",
1229 ty.with_ctx(ctx),
1230 op.with_ctx(ctx)
1231 )
1232 }
1233 }
1234 }
1235}
1236
1237impl Display for ScalarValue {
1238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1239 match self {
1240 ScalarValue::Isize(v) => write!(f, "{v} : isize"),
1241 ScalarValue::I8(v) => write!(f, "{v} : i8"),
1242 ScalarValue::I16(v) => write!(f, "{v} : i16"),
1243 ScalarValue::I32(v) => write!(f, "{v} : i32"),
1244 ScalarValue::I64(v) => write!(f, "{v} : i64"),
1245 ScalarValue::I128(v) => write!(f, "{v} : i128"),
1246 ScalarValue::Usize(v) => write!(f, "{v} : usize"),
1247 ScalarValue::U8(v) => write!(f, "{v} : u8"),
1248 ScalarValue::U16(v) => write!(f, "{v} : u16"),
1249 ScalarValue::U32(v) => write!(f, "{v} : u32"),
1250 ScalarValue::U64(v) => write!(f, "{v} : u64"),
1251 ScalarValue::U128(v) => write!(f, "{v} : u128"),
1252 }
1253 }
1254}
1255
1256impl<C: AstFormatter> FmtWithCtx<C> for ullbc::Statement {
1257 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1258 let tab = ctx.indent();
1259 use ullbc::RawStatement;
1260 for line in &self.comments_before {
1261 writeln!(f, "{tab}// {line}")?;
1262 }
1263 match &self.content {
1264 RawStatement::Assign(place, rvalue) => write!(
1265 f,
1266 "{tab}{} := {}",
1267 place.with_ctx(ctx),
1268 rvalue.with_ctx(ctx),
1269 ),
1270 RawStatement::SetDiscriminant(place, variant_id) => write!(
1271 f,
1272 "{tab}@discriminant({}) := {}",
1273 place.with_ctx(ctx),
1274 variant_id
1275 ),
1276 RawStatement::CopyNonOverlapping(box CopyNonOverlapping { src, dst, count }) => write!(
1277 f,
1278 "{}copy_nonoverlapping({}, {}, {})",
1279 tab,
1280 src.with_ctx(ctx),
1281 dst.with_ctx(ctx),
1282 count.with_ctx(ctx),
1283 ),
1284 RawStatement::StorageLive(var_id) => {
1285 write!(f, "{tab}storage_live({})", var_id.with_ctx(ctx))
1286 }
1287 RawStatement::StorageDead(var_id) => {
1288 write!(f, "{tab}storage_dead({})", var_id.with_ctx(ctx))
1289 }
1290 RawStatement::Deinit(place) => {
1291 write!(f, "{tab}deinit({})", place.with_ctx(ctx))
1292 }
1293 RawStatement::Drop(place) => {
1294 write!(f, "{tab}drop {}", place.with_ctx(ctx))
1295 }
1296 RawStatement::Assert(assert) => write!(f, "{tab}{}", assert.with_ctx(ctx)),
1297 RawStatement::Nop => write!(f, "{tab}nop"),
1298 RawStatement::Error(s) => write!(f, "{tab}@Error({})", s),
1299 }
1300 }
1301}
1302
1303impl<C: AstFormatter> FmtWithCtx<C> for llbc::Statement {
1304 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1305 let tab = ctx.indent();
1306 use llbc::RawStatement;
1307 for line in &self.comments_before {
1308 writeln!(f, "{tab}// {line}")?;
1309 }
1310 write!(f, "{tab}")?;
1311 match &self.content {
1312 RawStatement::Assign(place, rvalue) => {
1313 write!(f, "{} := {}", place.with_ctx(ctx), rvalue.with_ctx(ctx),)
1314 }
1315 RawStatement::SetDiscriminant(place, variant_id) => write!(
1316 f,
1317 "@discriminant({}) := {}",
1318 place.with_ctx(ctx),
1319 variant_id
1320 ),
1321 RawStatement::CopyNonOverlapping(box CopyNonOverlapping { src, dst, count }) => write!(
1322 f,
1323 "copy_nonoverlapping({}, {}, {})",
1324 src.with_ctx(ctx),
1325 dst.with_ctx(ctx),
1326 count.with_ctx(ctx),
1327 ),
1328 RawStatement::StorageLive(var_id) => {
1329 write!(f, "storage_live({})", var_id.with_ctx(ctx))
1330 }
1331 RawStatement::StorageDead(var_id) => {
1332 write!(f, "storage_dead({})", var_id.with_ctx(ctx))
1333 }
1334 RawStatement::Deinit(place) => {
1335 write!(f, "deinit({})", place.with_ctx(ctx))
1336 }
1337 RawStatement::Drop(place) => {
1338 write!(f, "drop {}", place.with_ctx(ctx))
1339 }
1340 RawStatement::Assert(assert) => {
1341 write!(f, "{}", assert.with_ctx(ctx),)
1342 }
1343 RawStatement::Call(call) => {
1344 write!(f, "{}", call.with_ctx(ctx))
1345 }
1346 RawStatement::Abort(kind) => {
1347 write!(f, "{}", kind.with_ctx(ctx))
1348 }
1349 RawStatement::Return => write!(f, "return"),
1350 RawStatement::Break(index) => write!(f, "break {index}"),
1351 RawStatement::Continue(index) => write!(f, "continue {index}"),
1352 RawStatement::Nop => write!(f, "nop"),
1353 RawStatement::Switch(switch) => match switch {
1354 Switch::If(discr, true_st, false_st) => {
1355 let ctx = &ctx.increase_indent();
1356 write!(
1357 f,
1358 "if {} {{\n{}{tab}}}\n{tab}else {{\n{}{tab}}}",
1359 discr.with_ctx(ctx),
1360 true_st.with_ctx(ctx),
1361 false_st.with_ctx(ctx),
1362 )
1363 }
1364 Switch::SwitchInt(discr, _ty, maps, otherwise) => {
1365 writeln!(f, "switch {} {{", discr.with_ctx(ctx))?;
1366 let ctx1 = &ctx.increase_indent();
1367 let inner_tab1 = ctx1.indent();
1368 let ctx2 = &ctx1.increase_indent();
1369 for (pvl, st) in maps {
1370 let pvl = pvl.iter().format(" | ");
1372 writeln!(
1373 f,
1374 "{inner_tab1}{} => {{\n{}{inner_tab1}}},",
1375 pvl,
1376 st.with_ctx(ctx2),
1377 )?;
1378 }
1379 writeln!(
1380 f,
1381 "{inner_tab1}_ => {{\n{}{inner_tab1}}},",
1382 otherwise.with_ctx(ctx2),
1383 )?;
1384 write!(f, "{tab}}}")
1385 }
1386 Switch::Match(discr, maps, otherwise) => {
1387 writeln!(f, "match {} {{", discr.with_ctx(ctx))?;
1388 let ctx1 = &ctx.increase_indent();
1389 let inner_tab1 = ctx1.indent();
1390 let ctx2 = &ctx1.increase_indent();
1391 let discr_type: Option<TypeDeclId> = discr
1392 .ty
1393 .kind()
1394 .as_adt()
1395 .and_then(|(x, _)| x.as_adt())
1396 .copied();
1397 for (cases, st) in maps {
1398 write!(f, "{inner_tab1}",)?;
1399 for (bar, v) in repeat_except_first(" | ").zip(cases.iter()) {
1401 write!(f, "{}", bar.unwrap_or_default())?;
1402 match discr_type {
1403 Some(type_id) => ctx.format_enum_variant(f, type_id, *v)?,
1404 None => write!(f, "{}", v.to_pretty_string())?,
1405 }
1406 }
1407 writeln!(f, " => {{\n{}{inner_tab1}}},", st.with_ctx(ctx2),)?;
1408 }
1409 if let Some(otherwise) = otherwise {
1410 writeln!(
1411 f,
1412 "{inner_tab1}_ => {{\n{}{inner_tab1}}},",
1413 otherwise.with_ctx(ctx2),
1414 )?;
1415 }
1416 write!(f, "{tab}}}")
1417 }
1418 },
1419 RawStatement::Loop(body) => {
1420 let ctx = &ctx.increase_indent();
1421 write!(f, "loop {{\n{}{tab}}}", body.with_ctx(ctx))
1422 }
1423 RawStatement::Error(s) => write!(f, "@ERROR({})", s),
1424 }
1425 }
1426}
1427
1428impl<C: AstFormatter> FmtWithCtx<C> for Terminator {
1429 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1430 let tab = ctx.indent();
1431 for line in &self.comments_before {
1432 writeln!(f, "{tab}// {line}")?;
1433 }
1434 write!(f, "{tab}")?;
1435 match &self.content {
1436 RawTerminator::Goto { target } => write!(f, "goto bb{target}"),
1437 RawTerminator::Switch { discr, targets } => match targets {
1438 SwitchTargets::If(true_block, false_block) => write!(
1439 f,
1440 "if {} -> bb{} else -> bb{}",
1441 discr.with_ctx(ctx),
1442 true_block,
1443 false_block
1444 ),
1445 SwitchTargets::SwitchInt(_ty, maps, otherwise) => {
1446 let maps = maps
1447 .iter()
1448 .map(|(v, bid)| format!("{}: bb{}", v.to_string(), bid))
1449 .chain([format!("otherwise: bb{otherwise}")])
1450 .format(", ");
1451 write!(f, "switch {} -> {}", discr.with_ctx(ctx), maps)
1452 }
1453 },
1454 RawTerminator::Call {
1455 call,
1456 target,
1457 on_unwind,
1458 } => {
1459 let call = call.with_ctx(ctx);
1460 write!(f, "{call} -> bb{target} (unwind: bb{on_unwind})",)
1461 }
1462 RawTerminator::Abort(kind) => write!(f, "{}", kind.with_ctx(ctx)),
1463 RawTerminator::Return => write!(f, "return"),
1464 RawTerminator::UnwindResume => write!(f, "unwind_continue"),
1465 }
1466 }
1467}
1468
1469impl<C: AstFormatter> FmtWithCtx<C> for TraitClause {
1470 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1471 let clause_id = self.clause_id.to_pretty_string();
1472 let trait_ = self.trait_.with_ctx(ctx);
1473 write!(f, "[{clause_id}]: {trait_}")
1474 }
1475}
1476
1477impl<C: AstFormatter> FmtWithCtx<C> for TraitDecl {
1478 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1479 let ctx = &ctx.set_generics(&self.generics);
1481
1482 self.item_meta
1483 .fmt_item_intro(f, ctx, "trait", self.def_id)?;
1484
1485 let (generics, clauses) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
1486 write!(f, "{generics}{clauses}")?;
1487
1488 let any_item = !self.parent_clauses.is_empty()
1489 || !self.type_clauses.is_empty()
1490 || !self.consts.is_empty()
1491 || !self.types.is_empty()
1492 || self.methods().count() > 0;
1493 if any_item {
1494 write!(f, "\n{{\n")?;
1495 for c in &self.parent_clauses {
1496 writeln!(
1497 f,
1498 "{TAB_INCR}parent_clause{} : {}",
1499 c.clause_id,
1500 c.with_ctx(ctx)
1501 )?;
1502 }
1503 for (name, clauses) in &self.type_clauses {
1504 for c in clauses {
1505 writeln!(
1506 f,
1507 "{TAB_INCR}item_clause_{name}_{} : {}",
1508 c.clause_id.to_string(),
1509 c.with_ctx(ctx)
1510 )?;
1511 }
1512 }
1513 for (name, ty) in &self.consts {
1514 let ty = ty.with_ctx(ctx);
1515 writeln!(f, "{TAB_INCR}const {name} : {ty}")?;
1516 }
1517 for name in &self.types {
1518 writeln!(f, "{TAB_INCR}type {name}")?;
1519 }
1520 for (name, bound_fn) in self.methods() {
1521 let (params, fn_ref) = bound_fn.fmt_split(ctx);
1522 writeln!(f, "{TAB_INCR}fn {name}{params} = {fn_ref}")?;
1523 }
1524 write!(f, "}}")?;
1525 }
1526 Ok(())
1527 }
1528}
1529
1530impl<C: AstFormatter> FmtWithCtx<C> for TraitDeclId {
1531 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1532 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
1533 }
1534}
1535
1536impl<C: AstFormatter> FmtWithCtx<C> for TraitDeclRef {
1537 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1538 let trait_id = self.trait_id.with_ctx(ctx);
1539 let generics = self.generics.with_ctx(ctx);
1540 write!(f, "{trait_id}{generics}")
1541 }
1542}
1543
1544impl<C: AstFormatter> FmtWithCtx<C> for TraitImpl {
1545 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1546 let full_name = self.item_meta.name.with_ctx(ctx);
1547 writeln!(f, "// Full name: {full_name}")?;
1548
1549 let ctx = &ctx.set_generics(&self.generics);
1551
1552 let (generics, clauses) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
1553 let mut impl_trait = self.impl_trait.clone();
1554 let self_ty = impl_trait.generics.types.remove(TypeVarId::ZERO).unwrap();
1555 let self_ty = self_ty.with_ctx(ctx);
1556 let impl_trait = impl_trait.with_ctx(ctx);
1557 write!(f, "impl{generics} {impl_trait} for {self_ty}{clauses}")?;
1558
1559 let newline = if clauses.is_empty() {
1560 " ".to_string()
1561 } else {
1562 "\n".to_string()
1563 };
1564 write!(f, "{newline}{{")?;
1565
1566 let any_item = !self.parent_trait_refs.is_empty()
1567 || !self.type_clauses.is_empty()
1568 || !self.consts.is_empty()
1569 || !self.types.is_empty()
1570 || self.methods().count() > 0;
1571 if any_item {
1572 writeln!(f)?;
1573 for (i, c) in self.parent_trait_refs.iter().enumerate() {
1574 let i = TraitClauseId::new(i);
1575 writeln!(f, "{TAB_INCR}parent_clause{i} = {}", c.with_ctx(ctx))?;
1576 }
1577 for (name, clauses) in &self.type_clauses {
1578 for (i, c) in clauses.iter().enumerate() {
1579 let i = TraitClauseId::new(i);
1580 writeln!(f, "{TAB_INCR}item_clause_{name}_{i} = {}", c.with_ctx(ctx))?;
1581 }
1582 }
1583 for (name, global) in &self.consts {
1584 writeln!(f, "{TAB_INCR}const {name} = {}", global.with_ctx(ctx))?;
1585 }
1586 for (name, ty) in &self.types {
1587 writeln!(f, "{TAB_INCR}type {name} = {}", ty.with_ctx(ctx))?;
1588 }
1589 for (name, bound_fn) in self.methods() {
1590 let (params, fn_ref) = bound_fn.fmt_split(ctx);
1591 writeln!(f, "{TAB_INCR}fn {name}{params} = {fn_ref}")?;
1592 }
1593 }
1594 write!(f, "}}")?;
1595 Ok(())
1596 }
1597}
1598
1599impl<C: AstFormatter> FmtWithCtx<C> for TraitImplId {
1600 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1601 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
1602 }
1603}
1604
1605impl Display for TraitItemName {
1606 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1607 write!(f, "{}", self.0)
1608 }
1609}
1610
1611impl<C: AstFormatter> FmtWithCtx<C> for TraitRefKind {
1612 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1613 match self {
1614 TraitRefKind::SelfId => write!(f, "Self"),
1615 TraitRefKind::ParentClause(id, _decl_id, clause_id) => {
1616 let id = id.with_ctx(ctx);
1617 write!(f, "{id}::parent_clause{clause_id}")
1618 }
1619 TraitRefKind::ItemClause(id, _decl_id, type_name, clause_id) => {
1620 let id = id.with_ctx(ctx);
1621 let clause = clause_id.to_pretty_string();
1624 write!(f, "({id}::{type_name}::[{clause}])")
1625 }
1626 TraitRefKind::TraitImpl(id, args) => {
1627 let impl_ = id.with_ctx(ctx);
1628 let args = args.with_ctx(ctx);
1629 write!(f, "{impl_}{args}")
1630 }
1631 TraitRefKind::Clause(id) => write!(f, "{}", id.with_ctx(ctx)),
1632 TraitRefKind::BuiltinOrAuto {
1633 trait_decl_ref: tr,
1634 types,
1635 ..
1636 } => {
1637 write!(f, "{}", tr.with_ctx(ctx))?;
1638 if !types.is_empty() {
1639 let types = types
1640 .iter()
1641 .map(|(name, ty)| {
1642 let ty = ty.with_ctx(ctx);
1643 format!("{name} = {ty}")
1644 })
1645 .join(", ");
1646 write!(f, " where {types}")?;
1647 }
1648 Ok(())
1649 }
1650 TraitRefKind::Dyn(tr) => write!(f, "{}", tr.with_ctx(ctx)),
1651 TraitRefKind::Unknown(msg) => write!(f, "UNKNOWN({msg})"),
1652 }
1653 }
1654}
1655
1656impl<C: AstFormatter> FmtWithCtx<C> for TraitRef {
1657 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1658 self.kind.fmt_with_ctx(ctx, f)
1659 }
1660}
1661
1662impl<C: AstFormatter> FmtWithCtx<C> for TraitTypeConstraint {
1663 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1664 let trait_ref = self.trait_ref.with_ctx(ctx);
1665 let ty = self.ty.with_ctx(ctx);
1666 write!(f, "{}::{} = {}", trait_ref, self.type_name, ty)
1667 }
1668}
1669
1670impl<C: AstFormatter> FmtWithCtx<C> for Ty {
1671 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1672 match self.kind() {
1673 TyKind::Adt(id, generics) => {
1674 let adt_ident = id.with_ctx(ctx);
1675 if id.is_tuple() {
1676 assert!(generics.trait_refs.is_empty());
1677 let generics = generics.fmt_explicits(ctx).format(", ");
1678 write!(f, "({generics})")
1679 } else {
1680 let generics = generics.with_ctx(ctx);
1681 write!(f, "{adt_ident}{generics}")
1682 }
1683 }
1684 TyKind::TypeVar(id) => write!(f, "{}", id.with_ctx(ctx)),
1685 TyKind::Literal(kind) => write!(f, "{kind}"),
1686 TyKind::Never => write!(f, "!"),
1687 TyKind::Ref(r, ty, kind) => {
1688 write!(f, "&{} ", r.with_ctx(ctx))?;
1689 if let RefKind::Mut = kind {
1690 write!(f, "mut ")?;
1691 }
1692 write!(f, "({})", ty.with_ctx(ctx))
1693 }
1694 TyKind::RawPtr(ty, kind) => {
1695 write!(f, "*")?;
1696 match kind {
1697 RefKind::Shared => write!(f, "const")?,
1698 RefKind::Mut => write!(f, "mut")?,
1699 }
1700 write!(f, " {}", ty.with_ctx(ctx))
1701 }
1702 TyKind::TraitType(trait_ref, name) => {
1703 write!(f, "{}::{name}", trait_ref.with_ctx(ctx),)
1704 }
1705 TyKind::DynTrait(pred) => write!(f, "dyn ({})", pred.with_ctx(ctx)),
1706 TyKind::Arrow(io) => {
1707 let ctx = &ctx.push_bound_regions(&io.regions);
1709
1710 write!(f, "fn")?;
1711 if !io.regions.is_empty() {
1712 write!(
1713 f,
1714 "<{}>",
1715 io.regions.iter().map(|r| r.with_ctx(ctx)).format(", ")
1716 )?;
1717 }
1718 let (inputs, output) = &io.skip_binder;
1719 let inputs = inputs.iter().map(|x| x.with_ctx(ctx)).format(", ");
1720 write!(f, "({inputs})")?;
1721 if !output.is_unit() {
1722 let output = output.with_ctx(ctx);
1723 write!(f, " -> {output}")?;
1724 }
1725 Ok(())
1726 }
1727 TyKind::Error(msg) => write!(f, "type_error(\"{msg}\")"),
1728 }
1729 }
1730}
1731
1732impl<C: AstFormatter> FmtWithCtx<C> for TypeDbVar {
1733 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1734 ctx.format_bound_var(f, *self, "@Type", |v| Some(v.to_string()))
1735 }
1736}
1737
1738impl<C: AstFormatter> FmtWithCtx<C> for TypeDecl {
1739 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1740 let keyword = match &self.kind {
1741 TypeDeclKind::Struct(..) => "struct",
1742 TypeDeclKind::Union(..) => "union",
1743 TypeDeclKind::Enum(..) => "enum",
1744 TypeDeclKind::Alias(..) => "type",
1745 TypeDeclKind::Opaque | TypeDeclKind::Error(..) => "opaque type",
1746 };
1747 self.item_meta
1748 .fmt_item_intro(f, ctx, keyword, self.def_id)?;
1749
1750 let ctx = &ctx.set_generics(&self.generics);
1751 let (params, preds) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
1752 write!(f, "{params}{preds}")?;
1753
1754 let nl_or_space = if !self.generics.has_predicates() {
1755 " ".to_string()
1756 } else {
1757 "\n".to_string()
1758 };
1759 match &self.kind {
1760 TypeDeclKind::Struct(fields) => {
1761 write!(f, "{nl_or_space}{{")?;
1762 if !fields.is_empty() {
1763 writeln!(f)?;
1764 for field in fields {
1765 writeln!(f, " {},", field.with_ctx(ctx))?;
1766 }
1767 }
1768 write!(f, "}}")
1769 }
1770 TypeDeclKind::Union(fields) => {
1771 write!(f, "{nl_or_space}{{")?;
1772 writeln!(f)?;
1773 for field in fields {
1774 writeln!(f, " {},", field.with_ctx(ctx))?;
1775 }
1776 write!(f, "}}")
1777 }
1778 TypeDeclKind::Enum(variants) => {
1779 write!(f, "{nl_or_space}{{")?;
1780 writeln!(f)?;
1781 for variant in variants {
1782 writeln!(f, " {},", variant.with_ctx(ctx))?;
1783 }
1784 write!(f, "}}")
1785 }
1786 TypeDeclKind::Alias(ty) => write!(f, " = {}", ty.with_ctx(ctx)),
1787 TypeDeclKind::Opaque => write!(f, ""),
1788 TypeDeclKind::Error(msg) => write!(f, " = ERROR({msg})"),
1789 }
1790 }
1791}
1792
1793impl<C: AstFormatter> FmtWithCtx<C> for TypeDeclId {
1794 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1795 AnyTransId::from(*self).fmt_with_ctx(ctx, f)
1796 }
1797}
1798
1799impl<C: AstFormatter> FmtWithCtx<C> for TypeId {
1800 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1801 match self {
1802 TypeId::Tuple => Ok(()),
1803 TypeId::Adt(def_id) => write!(f, "{}", def_id.with_ctx(ctx)),
1804 TypeId::Builtin(aty) => write!(f, "{}", aty.get_name().with_ctx(ctx)),
1805 }
1806 }
1807}
1808
1809impl_display_via_ctx!(TypeVar);
1810impl<C: AstFormatter> FmtWithCtx<C> for TypeVar {
1811 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1812 write!(f, "{}", self.name)
1813 }
1814}
1815
1816impl<C: AstFormatter> FmtWithCtx<C> for UnOp {
1817 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1818 match self {
1819 UnOp::Not => write!(f, "~"),
1820 UnOp::Neg => write!(f, "-"),
1821 UnOp::PtrMetadata => write!(f, "ptr_metadata"),
1822 UnOp::Cast(kind) => write!(f, "{}", kind.with_ctx(ctx)),
1823 UnOp::ArrayToSlice(..) => write!(f, "array_to_slice"),
1824 }
1825 }
1826}
1827
1828impl_display_via_ctx!(Variant);
1829impl<C: AstFormatter> FmtWithCtx<C> for Variant {
1830 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1831 write!(f, "{}", self.name)?;
1832 if !self.fields.is_empty() {
1833 let fields = self.fields.iter().map(|f| f.with_ctx(ctx)).format(", ");
1834 write!(f, "({})", fields)?;
1835 }
1836 Ok(())
1837 }
1838}