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