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