1use crate::{
3 common::{TAB_INCR, repeat_except_first},
4 formatter::*,
5 gast,
6 ids::IndexVec,
7 llbc_ast::{self as llbc, *},
8 transform::utils::GenericsSource,
9 ullbc_ast::{self as ullbc, *},
10};
11use either::Either;
12use itertools::Itertools;
13use std::{
14 borrow::Cow,
15 fmt::{self, Debug, Display},
16};
17
18pub struct WithCtx<'a, C, T: ?Sized> {
19 val: &'a T,
20 ctx: &'a C,
21}
22
23impl<'a, C, T: ?Sized> Display for WithCtx<'a, C, T>
24where
25 T: FmtWithCtx<C>,
26{
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 self.val.fmt_with_ctx(self.ctx, f)
29 }
30}
31
32pub trait FmtWithCtx<C> {
34 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result;
35
36 fn with_ctx<'a>(&'a self, ctx: &'a C) -> WithCtx<'a, C, Self> {
41 WithCtx { val: self, ctx }
42 }
43
44 fn to_string_with_ctx(&self, ctx: &C) -> String {
45 self.with_ctx(ctx).to_string()
46 }
47}
48
49macro_rules! impl_display_via_ctx {
50 ($ty:ty) => {
51 impl Display for $ty {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 self.fmt_with_ctx(&FmtCtx::new(), f)
54 }
55 }
56 };
57}
58macro_rules! impl_debug_via_display {
59 ($ty:ty) => {
60 impl Debug for $ty {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 <_ as Display>::fmt(self, f)
63 }
64 }
65 };
66}
67
68fn fmt_where_clauses<'a, I>(clauses: I, indent: &'a str) -> impl Display + 'a
69where
70 I: IntoIterator,
71 I::Item: Display,
72{
73 let clauses = clauses
74 .into_iter()
75 .map(|clause| clause.to_string())
76 .collect_vec();
77 std::fmt::from_fn(move |f| {
78 if !clauses.is_empty() {
79 write!(f, "\n{indent}where")?;
80 for (i, clause) in clauses.iter().enumerate() {
81 let sep = if i + 1 == clauses.len() { ";" } else { "," };
82 write!(f, "\n{indent}{TAB_INCR}{clause}{sep}")?;
83 }
84 }
85 Ok(())
86 })
87}
88
89impl<C: AstFormatter> FmtWithCtx<C> for AbortKind {
92 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 match self {
94 AbortKind::Panic(name) => {
95 write!(f, "panic")?;
96 if let Some(name) = name {
97 write!(f, "({})", name.with_ctx(ctx))?;
98 }
99 Ok(())
100 }
101 AbortKind::UndefinedBehavior => write!(f, "undefined_behavior"),
102 AbortKind::UnwindTerminate => write!(f, "unwind_terminate"),
103 }
104 }
105}
106
107impl<C: AstFormatter> FmtWithCtx<C> for Abi {
108 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 write!(f, "{}", self.rust_name())
110 }
111}
112
113impl<C: AstFormatter> FmtWithCtx<C> for BuiltinAssertKind {
114 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 match self {
116 BuiltinAssertKind::BoundsCheck { .. } => write!(f, "bounds_check"),
117 BuiltinAssertKind::Overflow(..) => write!(f, "overflow"),
118 BuiltinAssertKind::OverflowNeg(..) => write!(f, "overflow_neg"),
119 BuiltinAssertKind::DivisionByZero(..) => write!(f, "division_by_zero"),
120 BuiltinAssertKind::RemainderByZero(..) => write!(f, "remainder_by_zero"),
121 BuiltinAssertKind::MisalignedPointerDereference { .. } => {
122 write!(f, "misaligned_pointer_dereference")
123 }
124 BuiltinAssertKind::NullPointerDereference => write!(f, "null_pointer_dereference"),
125 BuiltinAssertKind::InvalidEnumConstruction(..) => {
126 write!(f, "invalid_enum_construction")
127 }
128 BuiltinAssertKind::ResumedAfterReturn => write!(f, "resumed_after_return"),
129 BuiltinAssertKind::ResumedAfterDrop => write!(f, "resumed_after_drop"),
130 BuiltinAssertKind::ResumedAfterPanic => write!(f, "resumed_after_panic"),
131 }
132 }
133}
134
135impl<C: AstFormatter> FmtWithCtx<C> for ItemId {
136 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 match ctx.get_crate() {
138 None => write!(f, "{self}"),
139 Some(translated) => translated.item_short_name(*self).fmt_with_ctx(ctx, f),
140 }
141 }
142}
143
144impl Display for ItemId {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
146 let s = match self {
147 ItemId::Type(x) => x.to_pretty_string(),
148 ItemId::Fun(x) => x.to_pretty_string(),
149 ItemId::Global(x) => x.to_pretty_string(),
150 ItemId::TraitDecl(x) => x.to_pretty_string(),
151 ItemId::TraitImpl(x) => x.to_pretty_string(),
152 };
153 f.write_str(&s)
154 }
155}
156
157impl<C: AstFormatter> FmtWithCtx<C> for ItemRef<'_> {
158 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 match self {
160 ItemRef::Type(d) => write!(f, "{}", d.with_ctx(ctx)),
161 ItemRef::Fun(d) => write!(f, "{}", d.with_ctx(ctx)),
162 ItemRef::Global(d) => write!(f, "{}", d.with_ctx(ctx)),
163 ItemRef::TraitDecl(d) => write!(f, "{}", d.with_ctx(ctx)),
164 ItemRef::TraitImpl(d) => write!(f, "{}", d.with_ctx(ctx)),
165 }
166 }
167}
168
169impl<C: AstFormatter> FmtWithCtx<C> for Assert {
170 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 write!(
172 f,
173 "assert({} == {})",
174 self.cond.with_ctx(ctx),
175 self.expected,
176 )?;
177 if let Some(check_kind) = &self.check_kind {
178 write!(f, " ({})", check_kind.with_ctx(ctx))?;
179 }
180 Ok(())
181 }
182}
183
184impl<T> Binder<T> {
185 fn fmt_split<'a, C>(&'a self, ctx: &'a C) -> (String, String)
187 where
188 C: AstFormatter,
189 T: FmtWithCtx<C::Reborrow<'a>>,
190 {
191 self.fmt_split_with(ctx, |ctx, x| x.to_string_with_ctx(ctx))
192 }
193 fn fmt_split_with<'a, C>(
195 &'a self,
196 ctx: &'a C,
197 fmt_inner: impl FnOnce(&C::Reborrow<'a>, &T) -> String,
198 ) -> (String, String)
199 where
200 C: AstFormatter,
201 {
202 let ctx = &ctx.push_binder(Cow::Borrowed(&self.params));
203 (
204 self.params.fmt_with_ctx_single_line(ctx),
205 fmt_inner(ctx, &self.skip_binder),
206 )
207 }
208}
209
210impl Display for OverflowMode {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
212 match self {
213 OverflowMode::Panic => write!(f, "panic"),
214 OverflowMode::Wrap => write!(f, "wrap"),
215 OverflowMode::UB => write!(f, "ub"),
216 }
217 }
218}
219
220impl Display for BinOp {
221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
222 match self {
223 BinOp::BitXor => write!(f, "^"),
224 BinOp::BitAnd => write!(f, "&"),
225 BinOp::BitOr => write!(f, "|"),
226 BinOp::Eq => write!(f, "=="),
227 BinOp::Lt => write!(f, "<"),
228 BinOp::Le => write!(f, "<="),
229 BinOp::Ne => write!(f, "!="),
230 BinOp::Ge => write!(f, ">="),
231 BinOp::Gt => write!(f, ">"),
232 BinOp::Add(mode) => write!(f, "{}.+", mode),
233 BinOp::Sub(mode) => write!(f, "{}.-", mode),
234 BinOp::Mul(mode) => write!(f, "{}.*", mode),
235 BinOp::Div(mode) => write!(f, "{}./", mode),
236 BinOp::Rem(mode) => write!(f, "{}.%", mode),
237 BinOp::AddChecked => write!(f, "checked.+"),
238 BinOp::SubChecked => write!(f, "checked.-"),
239 BinOp::MulChecked => write!(f, "checked.*"),
240 BinOp::Shl(mode) => write!(f, "{}.<<", mode),
241 BinOp::Shr(mode) => write!(f, "{}.>>", mode),
242 BinOp::Cmp => write!(f, "cmp"),
243 BinOp::Offset => write!(f, "offset"),
244 }
245 }
246}
247
248impl<C: AstFormatter> FmtWithCtx<C> for llbc::Block {
249 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 for st in &self.statements {
251 writeln!(f, "{}", st.with_ctx(ctx))?;
252 }
253 Ok(())
254 }
255}
256
257impl<C: AstFormatter> FmtWithCtx<C> for ullbc::BlockData {
258 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 for statement in &self.statements {
260 writeln!(f, "{};", statement.with_ctx(ctx))?;
261 }
262 write!(f, "{};", self.terminator.with_ctx(ctx))?;
263 Ok(())
264 }
265}
266
267impl<C: AstFormatter> FmtWithCtx<C> for gast::Body {
268 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269 let tab = ctx.indent();
270 write!(f, "\n{tab}")?;
271 match self {
272 Body::Unstructured(body) => {
273 let body = body.with_ctx(ctx);
274 write!(f, "{{\n{body}{tab}}}")
275 }
276 Body::Structured(body) => {
277 let body = body.with_ctx(ctx);
278 write!(f, "{{\n{body}{tab}}}")
279 }
280 Body::TraitMethodWithoutDefault => write!(f, "= <method_without_default_body>"),
281 Body::Extern(name) => write!(f, "= <extern:{name}>"),
282 Body::Intrinsic { name, .. } => write!(f, "= <intrinsic:{name}>"),
283 Body::Opaque => write!(f, "= <opaque>"),
284 Body::Missing => write!(f, "= <missing>"),
285 Body::Error(error) => write!(f, "= error(\"{}\")", error.msg),
286 Body::TargetDispatch(targets) => {
287 writeln!(f, "= target_dispatch {{")?;
288 for (target, fun) in targets {
289 let fun = fun.with_ctx(ctx);
290 writeln!(f, "{tab}{TAB_INCR}{target} => {fun},")?;
291 }
292 write!(f, "{tab}}}")
293 }
294 }
295 }
296}
297
298impl Display for BorrowKind {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
300 write!(f, "{self:?}")
302 }
303}
304
305impl Display for BuiltinFunId {
306 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
307 let name = match *self {
308 BuiltinFunId::BoxNew => "BoxNew",
309 BuiltinFunId::ArrayToSliceShared => "ArrayToSliceShared",
310 BuiltinFunId::ArrayToSliceMut => "ArrayToSliceMut",
311 BuiltinFunId::ArrayRepeat => "ArrayRepeat",
312 BuiltinFunId::Index(BuiltinIndexOp {
313 is_array,
314 mutability,
315 is_range,
316 }) => {
317 let ty = if is_array { "Array" } else { "Slice" };
318 let op = if is_range { "SubSlice" } else { "Index" };
319 let mutability = mutability.variant_name();
320 &format!("{ty}{op}{mutability}")
321 }
322 BuiltinFunId::PtrFromParts(mutability) => {
323 let mutability = mutability.variant_name();
324 &format!("PtrFromParts{mutability}")
325 }
326 };
327 f.write_str(name)
328 }
329}
330
331impl<C: AstFormatter> FmtWithCtx<C> for Call {
332 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333 let dest = self.dest.with_ctx(ctx);
334 let func = self.func.with_ctx(ctx);
335 let args = self.args.iter().map(|x| x.with_ctx(ctx)).format(", ");
336 write!(f, "{dest} = {func}({args})")
337 }
338}
339
340impl<C: AstFormatter> FmtWithCtx<C> for UnsizingMetadata {
341 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342 match self {
343 UnsizingMetadata::Length(len) => write!(f, "{}", len.with_ctx(ctx)),
344 UnsizingMetadata::VTable(_, vtable) => {
345 write!(f, "{}", vtable.with_ctx(ctx))
346 }
347 UnsizingMetadata::VTableUpcast(fields) => {
348 write!(f, " at [")?;
349 let fields = fields.iter().map(|x| format!("{}", x.index())).format(", ");
350 write!(f, "{fields}]")
351 }
352 UnsizingMetadata::Unknown => {
353 write!(f, "?")
354 }
355 }
356 }
357}
358
359impl<C: AstFormatter> FmtWithCtx<C> for CastKind {
360 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361 match self {
362 CastKind::Scalar(src, tgt) => write!(f, "cast<{src}, {tgt}>"),
363 CastKind::FnPtr(src, tgt) | CastKind::RawPtr(src, tgt) => {
364 write!(f, "cast<{}, {}>", src.with_ctx(ctx), tgt.with_ctx(ctx))
365 }
366 CastKind::Unsize(src, tgt, meta) => write!(
367 f,
368 "unsize_cast<{}, {}, {}>",
369 src.with_ctx(ctx),
370 tgt.with_ctx(ctx),
371 meta.with_ctx(ctx)
372 ),
373 CastKind::Transmute(src, tgt) => {
374 write!(f, "transmute<{}, {}>", src.with_ctx(ctx), tgt.with_ctx(ctx))
375 }
376 CastKind::Concretize(ty, ty1) => {
377 write!(f, "concretize<{}, {}>", ty.with_ctx(ctx), ty1.with_ctx(ctx))
378 }
379 }
380 }
381}
382
383impl<C: AstFormatter> FmtWithCtx<C> for ClauseDbVar {
384 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385 ctx.format_bound_var(f, *self, "TraitClause", |_| None)
386 }
387}
388
389impl<C: AstFormatter> FmtWithCtx<C> for ConstGenericDbVar {
390 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
391 ctx.format_bound_var(f, *self, "@ConstGeneric", |v| Some(v.name.clone()))
392 }
393}
394
395impl<C: AstFormatter> FmtWithCtx<C> for ConstGenericParam {
396 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
397 write!(f, "const {} : {}", self.name, self.ty.with_ctx(ctx))
398 }
399}
400
401impl Display for DeBruijnId {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
403 write!(f, "{}", self.index)
404 }
405}
406
407impl<Id: Display> Display for DeBruijnVar<Id> {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 match self {
410 Self::Bound(dbid, varid) => write!(f, "Bound({dbid}, {varid})"),
411 Self::Free(varid) => write!(f, "{varid}"),
412 }
413 }
414}
415
416impl<C: AstFormatter> FmtWithCtx<C> for DeclarationGroup {
417 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418 use DeclarationGroup::*;
419 match self {
420 Type(g) => write!(f, "Type decls group: {}", g.with_ctx(ctx)),
421 Fun(g) => write!(f, "Fun decls group: {}", g.with_ctx(ctx)),
422 Global(g) => write!(f, "Global decls group: {}", g.with_ctx(ctx)),
423 TraitDecl(g) => write!(f, "Trait decls group: {}", g.with_ctx(ctx)),
424 TraitImpl(g) => write!(f, "Trait impls group: {}", g.with_ctx(ctx)),
425 Mixed(g) => write!(f, "Mixed group: {}", g.with_ctx(ctx)),
426 }
427 }
428}
429
430impl<C: AstFormatter> FmtWithCtx<C> for DynPredicate {
431 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432 let params = &self.binder.params;
433 let ctx = &ctx.push_binder(Cow::Borrowed(params));
434 let GenericParams {
435 regions,
436 types,
437 const_generics,
438 trait_clauses,
439 regions_outlive,
440 types_outlive,
441 trait_type_constraints,
442 } = params;
443 assert!(regions.is_empty());
444 assert!(const_generics.is_empty());
445 assert!(regions_outlive.is_empty());
446 assert_eq!(types.len(), 1);
447
448 let mut cstrs_per_clause: IndexVec<TraitClauseId, Vec<String>> =
450 trait_clauses.map_ref(|_| vec![]);
451 for cstr in trait_type_constraints {
452 let mut tgt_clause = None;
453 let (_, cstr) = cstr.fmt_split_with(ctx, |ctx, cstr| {
454 let mut path = vec![];
455 let mut tref = &cstr.trait_ref;
456 loop {
457 match &tref.kind {
458 TraitRefKind::ParentClause(parent_trait_ref, clause_id) => {
459 path.push(*clause_id);
460 tref = parent_trait_ref;
461 }
462 &TraitRefKind::Clause(DeBruijnVar::Bound(_, clause_id)) => {
463 tgt_clause = Some(clause_id);
464 break;
465 }
466 _ => unreachable!(),
467 }
468 }
469 let ty = cstr.ty.with_ctx(ctx);
470 let path_fmt = path.iter().map(|id| id.format_as_implied()).format("::");
471 std::fmt::from_fn(|f| {
472 write!(f, "{path_fmt}")?;
473 if !path.is_empty() {
474 write!(f, "::")?;
475 }
476 ctx.format_assoc_type_name(f, cstr.trait_ref.trait_id(), cstr.type_id)?;
477 write!(f, " = {ty}")?;
478 Ok(())
479 })
480 .to_string()
481 });
482 if let Some(cstrs) = cstrs_per_clause.get_mut(tgt_clause.unwrap()) {
483 cstrs.push(cstr);
484 }
485 }
486 let trait_clauses = trait_clauses.iter().map(|clause| {
487 let cstrs = &cstrs_per_clause[clause.clause_id];
488 clause.trait_.fmt_as_for_with(ctx, |ctx, pred| {
489 let (_, pred) = pred.split_self();
490 let trait_id = pred.id.with_ctx(ctx);
491 let generics = if pred.generics.has_explicits() || !cstrs.is_empty() {
492 let xs = pred
493 .generics
494 .fmt_explicits(ctx)
495 .map(Either::Left)
496 .chain(cstrs.iter().map(Either::Right))
497 .format(", ");
498 format!("<{}>", xs)
499 } else {
500 String::new()
501 };
502 format!("{trait_id}{generics}")
503 })
504 });
505
506 let types_outlive = types_outlive
507 .iter()
508 .filter(|x| !x.skip_binder.1.is_erased())
509 .map(|x| {
510 x.fmt_as_for_with(ctx, |ctx, types_outlive| {
511 types_outlive.1.to_string_with_ctx(ctx)
512 })
513 });
514 let clauses = trait_clauses.chain(types_outlive).format(" + ");
515 write!(f, "{clauses}")
516 }
517}
518
519impl_display_via_ctx!(Field);
520impl<C: AstFormatter> FmtWithCtx<C> for Field {
521 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522 if let Some(name) = &self.name {
523 write!(f, "{}: ", name)?
524 }
525 write!(f, "{}", self.ty.with_ctx(ctx))
526 }
527}
528
529impl Display for FileName {
530 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
531 match self {
532 FileName::Virtual(path_buf) | FileName::Local(path_buf) => {
533 write!(f, "{}", path_buf.display())
534 }
535 FileName::NotReal(name) => write!(f, "{}", name),
536 }
537 }
538}
539
540impl Display for FloatTy {
541 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
542 match self {
543 FloatTy::F16 => write!(f, "f16"),
544 FloatTy::F32 => write!(f, "f32"),
545 FloatTy::F64 => write!(f, "f64"),
546 FloatTy::F128 => write!(f, "f128"),
547 }
548 }
549}
550
551impl Display for FloatValue {
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
553 let v = &self.value;
554 let ty = self.ty;
555 write!(f, "{v}{ty}")
556 }
557}
558
559impl<C: AstFormatter> FmtWithCtx<C> for FnOperand {
560 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561 match self {
562 FnOperand::Regular(func) => write!(f, "{}", func.with_ctx(ctx)),
563 FnOperand::Dynamic(op) => write!(f, "({})", op.with_ctx(ctx)),
564 }
565 }
566}
567
568impl<C: AstFormatter> FmtWithCtx<C> for FnPtr {
569 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
570 match self.kind.as_ref() {
571 FnPtrKind::Fun(FunId::Regular(def_id)) => write!(f, "{}", def_id.with_ctx(ctx))?,
572 FnPtrKind::Fun(FunId::Builtin(builtin)) => write!(f, "@{}", builtin)?,
573 FnPtrKind::Trait(trait_ref, method_id, _) => {
574 write!(f, "{}::", trait_ref.with_ctx(ctx))?;
575 ctx.format_method_name(f, trait_ref.trait_id(), *method_id)?;
576 }
577 };
578 write!(f, "{}", self.generics.with_ctx(ctx))
579 }
580}
581
582impl<C: AstFormatter> FmtWithCtx<C> for FunDecl {
583 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584 let mut keyword = String::new();
585 if self.signature.is_unsafe {
586 keyword.push_str("unsafe ");
587 }
588 if !self.signature.abi.is_rust() {
589 keyword.push_str(&format!("extern \"{}\" ", self.signature.abi.with_ctx(ctx)));
590 }
591 keyword.push_str("fn");
592 self.item_meta
593 .fmt_item_intro(f, ctx, &keyword, self.def_id)?;
594
595 let ctx = &ctx.set_generics(&self.generics);
597
598 let (params, preds) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
600 write!(f, "{params}")?;
601
602 let n_args = self.signature.inputs.len();
604 let args_of_locals = |l: &Locals| {
605 l.locals
606 .iter()
607 .skip(1)
608 .take(n_args)
609 .map(|l| format!("{l}"))
610 .collect::<Vec<String>>()
611 };
612
613 let arg_names = match &self.body {
614 Body::Unstructured(body) => args_of_locals(&body.locals),
615 Body::Structured(body) => args_of_locals(&body.locals),
616 Body::Intrinsic { arg_names, .. } => arg_names
617 .iter()
618 .enumerate()
619 .map(|(i, name)| {
620 let id = LocalId::new(i + 1);
621 match name {
622 Some(name) => format!("{name}_{id}"),
623 None => format!("_{id}"),
624 }
625 })
626 .collect(),
627 Body::Error(..)
628 | Body::Extern(..)
629 | Body::Missing
630 | Body::Opaque
631 | Body::TraitMethodWithoutDefault
632 | Body::TargetDispatch(..) => (0..n_args)
633 .map(|i| format!("{}", LocalId::new(i + 1).with_ctx(ctx)))
634 .collect(),
635 };
636 let mut args: Vec<String> = Vec::new();
637 for (ty, name) in self.signature.inputs.iter().zip(arg_names) {
638 args.push(format!("{}: {}", name, ty.with_ctx(ctx)));
639 }
640 let args = args.join(", ");
641 write!(f, "({args})")?;
642
643 if !self.signature.output.is_unit() {
645 write!(f, " -> {}", self.signature.output.with_ctx(ctx))?;
646 };
647 write!(f, "{preds}")?;
648 write!(f, "{}", self.body.with_ctx(ctx))?;
649
650 Ok(())
651 }
652}
653
654impl<C: AstFormatter> FmtWithCtx<C> for FunDeclId {
655 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
656 ItemId::from(*self).fmt_with_ctx(ctx, f)
657 }
658}
659
660impl<C: AstFormatter> FmtWithCtx<C> for FunDeclRef {
661 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
662 let id = self.id.with_ctx(ctx);
663 let generics = self.generics.with_ctx(ctx);
664 write!(f, "{id}{generics}")
665 }
666}
667
668impl<C: AstFormatter> FmtWithCtx<C> for RegionBinder<FunSig> {
669 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
670 let ctx = &ctx.push_bound_regions(&self.regions);
672 let FunSig {
673 is_unsafe,
674 abi,
675 inputs,
676 output,
677 } = &self.skip_binder;
678
679 if *is_unsafe {
680 write!(f, "unsafe ")?;
681 }
682
683 if !abi.is_rust() {
684 write!(f, "extern \"{}\" ", abi.with_ctx(ctx))?;
685 }
686
687 write!(f, "fn")?;
688 if !self.regions.is_empty() {
689 write!(
690 f,
691 "<{}>",
692 self.regions.iter().map(|r| r.with_ctx(ctx)).format(", ")
693 )?;
694 }
695 let inputs = inputs.iter().map(|x| x.with_ctx(ctx)).format(", ");
696 write!(f, "({inputs})")?;
697 if !output.is_unit() {
698 let output = output.with_ctx(ctx);
699 write!(f, " -> {output}")?;
700 }
701 Ok(())
702 }
703}
704
705impl<Id: Copy, C: AstFormatter> FmtWithCtx<C> for GDeclarationGroup<Id>
706where
707 Id: FmtWithCtx<C>,
708{
709 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
710 use GDeclarationGroup::*;
711 match self {
712 NonRec(id) => write!(f, "Non rec: {}", id.with_ctx(ctx)),
713 Rec(ids) => {
714 let ids = ids.iter().map(|id| id.with_ctx(ctx)).format(", ");
715 write!(f, "Rec: {}", ids)
716 }
717 }
718 }
719}
720
721impl GenericArgs {
722 pub(crate) fn fmt_explicits<'a, C: AstFormatter>(
723 &'a self,
724 ctx: &'a C,
725 ) -> impl Iterator<Item = impl Display + 'a> {
726 let regions = self.regions.iter().map(|x| x.with_ctx(ctx));
727 let types = self.types.iter().map(|x| x.with_ctx(ctx));
728 let const_generics = self.const_generics.iter().map(|x| x.with_ctx(ctx));
729 regions.map(Either::Left).chain(
730 types
731 .map(Either::Left)
732 .chain(const_generics.map(Either::Right))
733 .map(Either::Right),
734 )
735 }
736
737 pub(crate) fn fmt_implicits<'a, C: AstFormatter>(
738 &'a self,
739 ctx: &'a C,
740 ) -> impl Iterator<Item = impl Display + 'a> {
741 self.trait_refs.iter().map(|x| x.with_ctx(ctx))
742 }
743}
744
745impl_display_via_ctx!(GenericArgs);
746impl_debug_via_display!(GenericArgs);
747impl<C: AstFormatter> FmtWithCtx<C> for GenericArgs {
748 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
749 if self.has_explicits() {
750 write!(f, "<{}>", self.fmt_explicits(ctx).format(", "))?;
751 }
752 if self.has_implicits() {
753 write!(f, "[{}]", self.fmt_implicits(ctx).format(", "))?;
754 }
755 Ok(())
756 }
757}
758
759impl GenericParams {
760 fn formatted_params<'a, C>(&'a self, ctx: &'a C) -> impl Iterator<Item = impl Display + 'a>
761 where
762 C: AstFormatter,
763 {
764 let regions = self.regions.iter().map(|x| x.with_ctx(ctx));
765 let types = self.types.iter().map(|x| x.with_ctx(ctx));
766 let const_generics = self.const_generics.iter().map(|x| x.with_ctx(ctx));
767 regions.map(Either::Left).chain(
768 types
769 .map(Either::Left)
770 .chain(const_generics.map(Either::Right))
771 .map(Either::Right),
772 )
773 }
774
775 fn formatted_clauses<'a, C>(&'a self, ctx: &'a C) -> impl Iterator<Item = impl Display + 'a>
776 where
777 C: AstFormatter,
778 {
779 let trait_clauses = self.trait_clauses.iter().map(|x| x.to_string_with_ctx(ctx));
780 let types_outlive = self
781 .types_outlive
782 .iter()
783 .enumerate()
784 .map(|(i, x)| format!("TypeOutlives{i}: {}", x.fmt_as_for(ctx)));
785 let regions_outlive = self
786 .regions_outlive
787 .iter()
788 .enumerate()
789 .map(|(i, x)| format!("RegionOutlives{i}: {}", x.fmt_as_for(ctx)));
790 let type_constraints = self
791 .trait_type_constraints
792 .iter_enumerated()
793 .map(|(i, x)| format!("TypeConstraint{i}: {}", x.fmt_as_for(ctx)));
794 trait_clauses.map(Either::Left).chain(
795 types_outlive
796 .chain(regions_outlive)
797 .chain(type_constraints)
798 .map(Either::Right),
799 )
800 }
801
802 pub fn fmt_with_ctx_with_trait_clauses<C>(&self, ctx: &C) -> (String, String)
803 where
804 C: AstFormatter,
805 {
806 let tab = ctx.indent();
807 let params = if self.has_explicits() {
808 let params = self.formatted_params(ctx).format(", ");
809 format!("<{}>", params)
810 } else {
811 String::new()
812 };
813 let clauses = if self.has_predicates() {
814 let clauses = self
815 .formatted_clauses(ctx)
816 .map(|x| format!("\n{tab}{TAB_INCR}{x},"))
817 .format("");
818 format!("\n{tab}where{clauses}")
819 } else {
820 String::new()
821 };
822 (params, clauses)
823 }
824
825 pub fn fmt_with_ctx_single_line<C>(&self, ctx: &C) -> String
826 where
827 C: AstFormatter,
828 {
829 if self.is_empty() {
830 String::new()
831 } else {
832 let params = self
833 .formatted_params(ctx)
834 .map(Either::Left)
835 .chain(self.formatted_clauses(ctx).map(Either::Right))
836 .format(", ");
837 format!("<{}>", params)
838 }
839 }
840}
841
842impl_debug_via_display!(GenericParams);
843impl Display for GenericParams {
844 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
845 write!(f, "{}", self.fmt_with_ctx_single_line(&FmtCtx::new()))
846 }
847}
848
849impl<C: AstFormatter> FmtWithCtx<C> for GenericsSource {
850 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
851 match self {
852 GenericsSource::Item(id) => write!(f, "{}", id.with_ctx(ctx)),
853 GenericsSource::Method(id, name) => write!(f, "{}::{name}", id.with_ctx(ctx)),
854 GenericsSource::TraitType(id, name) => {
855 write!(f, "{}::", id.with_ctx(ctx))?;
856 ctx.format_assoc_type_name(f, *id, *name)
857 }
858 GenericsSource::Builtin => write!(f, "<builtin>"),
859 GenericsSource::Other => write!(f, "<unknown>"),
860 }
861 }
862}
863
864impl<T> GExprBody<T> {
865 fn fmt_with_ctx_and_callback<C: AstFormatter>(
866 &self,
867 ctx: &C,
868 f: &mut fmt::Formatter<'_>,
869 fmt_body: impl FnOnce(
870 &mut fmt::Formatter<'_>,
871 &<<C as AstFormatter>::Reborrow<'_> as AstFormatter>::Reborrow<'_>,
872 &T,
873 ) -> fmt::Result,
874 ) -> fmt::Result {
875 let ctx = &ctx.set_locals(&self.locals);
877 let ctx = &ctx.increase_indent();
878 let tab = ctx.indent();
879
880 for v in &self.locals.locals {
882 write!(f, "{tab}")?;
883 write!(f, "let {v}: {};", v.ty.with_ctx(ctx))?;
884
885 write!(f, " // ")?;
886 if v.index.is_zero() {
887 write!(f, "return")?;
888 } else if self.locals.is_return_or_arg(v.index) {
889 write!(f, "arg #{}", v.index.index())?
890 } else {
891 match &v.name {
892 Some(_) => write!(f, "local")?,
893 None => write!(f, "anonymous local")?,
894 }
895 }
896 writeln!(f)?;
897 }
898
899 fmt_body(f, ctx, &self.body)?;
900
901 Ok(())
902 }
903}
904
905impl<C: AstFormatter> FmtWithCtx<C> for GExprBody<llbc_ast::Block> {
906 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
907 fn fmt_body<C: AstFormatter>(
909 f: &mut fmt::Formatter<'_>,
910 ctx: &<<C as AstFormatter>::Reborrow<'_> as AstFormatter>::Reborrow<'_>,
911 body: &Block,
912 ) -> Result<(), fmt::Error> {
913 writeln!(f)?;
914 body.fmt_with_ctx(ctx, f)?;
915 Ok(())
916 }
917 self.fmt_with_ctx_and_callback(ctx, f, fmt_body::<C>)
918 }
919}
920impl<C: AstFormatter> FmtWithCtx<C> for GExprBody<ullbc_ast::BodyContents> {
921 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
922 fn fmt_body<C: AstFormatter>(
924 f: &mut fmt::Formatter<'_>,
925 ctx: &<<C as AstFormatter>::Reborrow<'_> as AstFormatter>::Reborrow<'_>,
926 body: &IndexVec<BlockId, BlockData>,
927 ) -> Result<(), fmt::Error> {
928 let tab = ctx.indent();
929 let ctx = &ctx.increase_indent();
930 for (bid, block) in body.iter_enumerated() {
931 writeln!(f)?;
932 writeln!(f, "{tab}bb{}: {{", bid.index())?;
933 writeln!(f, "{}", block.with_ctx(ctx))?;
934 writeln!(f, "{tab}}}")?;
935 }
936 Ok(())
937 }
938 self.fmt_with_ctx_and_callback(ctx, f, fmt_body::<C>)
939 }
940}
941
942impl<C> FmtWithCtx<C> for GlobalDecl
943where
944 C: AstFormatter,
945{
946 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
947 let keyword = match self.global_kind {
948 GlobalKind::Static => "static",
949 GlobalKind::ThreadLocal => "thread_local",
950 GlobalKind::AnonConst | GlobalKind::NamedConst => "const",
951 };
952 self.item_meta
953 .fmt_item_intro(f, ctx, keyword, self.def_id)?;
954
955 let ctx = &ctx.set_generics(&self.generics);
957
958 let (params, preds) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
960
961 let ty = self.ty.with_ctx(ctx);
963 write!(f, "{params}: {ty}")?;
964
965 write!(f, "{preds}")?;
967 if self.generics.has_predicates() {
968 writeln!(f)?;
969 }
970 write!(f, " ")?;
971
972 let value = self.value.with_ctx(ctx);
974 write!(f, "= {value}")?;
975
976 Ok(())
977 }
978}
979
980impl<C: AstFormatter> FmtWithCtx<C> for GlobalDeclId {
981 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
982 ItemId::from(*self).fmt_with_ctx(ctx, f)
983 }
984}
985
986impl<C: AstFormatter> FmtWithCtx<C> for GlobalDeclRef {
987 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
988 let id = self.id.with_ctx(ctx);
989 let generics = self.generics.with_ctx(ctx);
990 write!(f, "{id}{generics}")
991 }
992}
993
994impl<C: AstFormatter> FmtWithCtx<C> for ImplElem {
995 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
996 write!(f, "{{")?;
997 match self {
998 ImplElem::Ty(bound_ty) => {
999 let ctx = ctx.set_generics(&bound_ty.params);
1001 bound_ty.skip_binder.fmt_with_ctx(&ctx, f)?
1002 }
1003 ImplElem::Trait(impl_id) => {
1004 match ctx.get_crate().and_then(|tr| tr.trait_impls.get(*impl_id)) {
1005 None => write!(f, "impl#{impl_id}")?,
1006 Some(timpl) => {
1007 let ctx = &ctx.set_generics(&timpl.generics);
1010 let mut impl_trait = timpl.impl_trait.clone();
1011 match impl_trait
1012 .generics
1013 .types
1014 .remove_and_shift_ids(TypeVarId::ZERO)
1015 {
1016 Some(self_ty) => {
1017 let self_ty = self_ty.with_ctx(ctx);
1018 let impl_trait = impl_trait.with_ctx(ctx);
1019 write!(f, "impl {impl_trait} for {self_ty}")?;
1020 }
1021 None => {
1023 let impl_trait = impl_trait.with_ctx(ctx);
1024 write!(f, "impl {impl_trait}")?;
1025 }
1026 }
1027 }
1028 }
1029 }
1030 }
1031 write!(f, "}}")
1032 }
1033}
1034
1035impl Display for IntTy {
1036 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1037 match self {
1038 IntTy::Isize => write!(f, "isize"),
1039 IntTy::I8 => write!(f, "i8"),
1040 IntTy::I16 => write!(f, "i16"),
1041 IntTy::I32 => write!(f, "i32"),
1042 IntTy::I64 => write!(f, "i64"),
1043 IntTy::I128 => write!(f, "i128"),
1044 }
1045 }
1046}
1047
1048impl Display for UIntTy {
1049 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1050 match self {
1051 UIntTy::Usize => write!(f, "usize"),
1052 UIntTy::U8 => write!(f, "u8"),
1053 UIntTy::U16 => write!(f, "u16"),
1054 UIntTy::U32 => write!(f, "u32"),
1055 UIntTy::U64 => write!(f, "u64"),
1056 UIntTy::U128 => write!(f, "u128"),
1057 }
1058 }
1059}
1060
1061impl Display for IntegerTy {
1062 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1063 match self {
1064 IntegerTy::Signed(int_ty) => write!(f, "{int_ty}"),
1065 IntegerTy::Unsigned(uint_ty) => write!(f, "{uint_ty}"),
1066 }
1067 }
1068}
1069
1070fn trait_impl_short_name<C: AstFormatter>(ctx: &C, impl_id: TraitImplId) -> Option<&Name> {
1071 ctx.get_crate()
1072 .and_then(|tr| tr.short_names.get(&ItemId::TraitImpl(impl_id)))
1073 .filter(|name| matches!(name.name.first(), Some(PathElem::Ident(..))))
1074}
1075
1076impl ItemMeta {
1077 pub fn fmt_item_intro<C: AstFormatter>(
1079 &self,
1080 f: &mut fmt::Formatter<'_>,
1081 ctx: &C,
1082 keyword: &str,
1083 id: impl Into<ItemId>,
1084 ) -> fmt::Result {
1085 let tab = ctx.indent();
1086 let id = id.into();
1087 let mut name = &self.name;
1088 let mut name_is_full = true;
1089 if let Some(tr) = ctx.get_crate()
1090 && let Some(short_name) = tr.short_names.get(&id)
1091 {
1092 name = short_name;
1093 name_is_full = false;
1094 } else if self
1095 .name
1096 .name
1097 .iter()
1098 .filter_map(|ne| ne.as_impl()?.as_trait())
1099 .any(|impl_id| trait_impl_short_name(ctx, *impl_id).is_some())
1100 {
1101 name_is_full = false;
1102 };
1103 if !name_is_full {
1104 writeln!(f, "// Full name: {}", self.name.full_name(ctx))?;
1105 }
1106
1107 if let Some(id) = &self.lang_item {
1108 writeln!(f, "{tab}#[lang_item(\"{id}\")]")?;
1109 }
1110 write!(f, "{tab}")?;
1111 if self.attr_info.public {
1112 write!(f, "pub ")?;
1113 }
1114 write!(f, "{keyword} {}", name.with_ctx(ctx))
1115 }
1116}
1117
1118impl Display for Literal {
1119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1120 match self {
1121 Literal::Scalar(v) => write!(f, "{v}"),
1122 Literal::Float(v) => write!(f, "{v}"),
1123 Literal::Bool(v) => write!(f, "{v}"),
1124 Literal::Char(v) => write!(f, "{v}"),
1125 Literal::Str(v) => write!(f, "\"{}\"", v.replace("\\", "\\\\").replace("\n", "\\n")),
1126 Literal::ByteStr(v) => write!(f, "{v:?}"),
1127 }
1128 }
1129}
1130
1131impl Display for LiteralTy {
1132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1133 match self {
1134 LiteralTy::Int(ty) => write!(f, "{ty}"),
1135 LiteralTy::UInt(ty) => write!(f, "{ty}"),
1136 LiteralTy::Float(ty) => write!(f, "{ty}"),
1137 LiteralTy::Char => write!(f, "char"),
1138 LiteralTy::Bool => write!(f, "bool"),
1139 }
1140 }
1141}
1142
1143impl Display for Loc {
1144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1145 write!(f, "{}:{}", self.line, self.col)
1146 }
1147}
1148
1149impl Display for Local {
1150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1151 if let Some(name) = &self.name {
1154 write!(f, "{name}")?
1155 }
1156 write!(f, "_{}", self.index)?;
1157 Ok(())
1158 }
1159}
1160
1161impl<C: AstFormatter> FmtWithCtx<C> for LocalId {
1162 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1163 ctx.format_local_id(f, *self)
1164 }
1165}
1166
1167impl<C: AstFormatter> FmtWithCtx<C> for Name {
1168 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1169 let ctx = &ctx.no_generics();
1172 let name = self.name.iter().map(|x| x.with_ctx(ctx)).format("::");
1173 write!(f, "{}", name)
1174 }
1175}
1176
1177impl Name {
1178 fn full_name<'a, C: AstFormatter + 'a>(&'a self, ctx: &'a C) -> impl Display + 'a {
1181 std::fmt::from_fn(move |f| {
1182 let ctx = &ctx.no_generics();
1183 let name = self
1184 .name
1185 .iter()
1186 .map(|elem| match elem {
1187 PathElem::Impl(impl_elem) => Either::Left(impl_elem.with_ctx(ctx)),
1188 _ => Either::Right(elem.with_ctx(ctx)),
1189 })
1190 .format("::");
1191 write!(f, "{name}")
1192 })
1193 }
1194}
1195
1196impl<C: AstFormatter> FmtWithCtx<C> for NullOp {
1197 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1198 let op = match self {
1199 NullOp::SizeOf => "size_of",
1200 NullOp::AlignOf => "align_of",
1201 &NullOp::OffsetOf(ref ty, variant, field) => {
1202 let tid = *ty.id.as_adt().expect("found offset_of of a non-adt type");
1203 write!(f, "offset_of({}.", ty.with_ctx(ctx))?;
1204 if let Some(variant) = variant {
1205 ctx.format_enum_variant_name(f, tid, variant)?;
1206 write!(f, ".")?;
1207 }
1208 ctx.format_field_name(f, tid, variant, field)?;
1209 write!(f, ")")?;
1210 return Ok(());
1211 }
1212 NullOp::UbChecks => "ub_checks",
1213 NullOp::OverflowChecks => "overflow_checks",
1214 NullOp::ContractChecks => "contract_checks",
1215 };
1216 write!(f, "{op}")
1217 }
1218}
1219
1220impl_display_via_ctx!(Operand);
1221impl<C: AstFormatter> FmtWithCtx<C> for Operand {
1222 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1223 match self {
1224 Operand::Copy(p) => write!(f, "copy {}", p.with_ctx(ctx)),
1225 Operand::Move(p) => write!(f, "move {}", p.with_ctx(ctx)),
1226 Operand::Const(c) => write!(f, "const {}", c.with_ctx(ctx)),
1227 }
1228 }
1229}
1230
1231impl<C: AstFormatter, T, U> FmtWithCtx<C> for OutlivesPred<T, U>
1232where
1233 T: FmtWithCtx<C>,
1234 U: FmtWithCtx<C>,
1235{
1236 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1237 write!(f, "{}: {}", self.0.with_ctx(ctx), self.1.with_ctx(ctx))
1238 }
1239}
1240
1241impl<C: AstFormatter> FmtWithCtx<C> for PathElem {
1242 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1243 match self {
1244 PathElem::Ident(s, d) => {
1245 write!(f, "{s}")?;
1246 if !d.is_zero() {
1247 write!(f, "#{}", d)?;
1248 }
1249 Ok(())
1250 }
1251 PathElem::Impl(impl_elem) => {
1252 if let ImplElem::Trait(impl_id) = impl_elem
1253 && let Some(short_name) = trait_impl_short_name(ctx, *impl_id)
1254 {
1255 return write!(f, "{}", short_name.with_ctx(ctx));
1256 }
1257 write!(f, "{}", impl_elem.with_ctx(ctx))
1258 }
1259 PathElem::Instantiated(binder) => {
1260 let underscore = "_".to_string();
1262 let params = GenericParams {
1263 regions: binder.params.regions.map_ref(|x| RegionParam {
1264 name: Some(underscore.clone()),
1265 ..*x
1266 }),
1267 types: binder.params.types.map_ref(|x| TypeParam {
1268 name: underscore.clone(),
1269 ..*x
1270 }),
1271 const_generics: binder.params.const_generics.map_ref(|x| ConstGenericParam {
1272 name: underscore.clone(),
1273 ty: x.ty.clone(),
1274 index: x.index,
1275 }),
1276 trait_clauses: binder.params.trait_clauses.clone(),
1277 ..GenericParams::empty()
1278 };
1279 let ctx = &ctx.push_binder(Cow::Owned(params));
1280 write!(
1281 f,
1282 "<{}>",
1283 binder.skip_binder.fmt_explicits(ctx).format(", ")
1284 )
1285 }
1286 PathElem::Target(target) => write!(f, "{target}"),
1287 }
1288 }
1289}
1290
1291impl_display_via_ctx!(Place);
1292impl<C: AstFormatter> FmtWithCtx<C> for Place {
1293 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1294 match &self.kind {
1295 PlaceKind::Local(var_id) => write!(f, "{}", var_id.with_ctx(ctx)),
1296 PlaceKind::Global(global_ref) => global_ref.fmt_with_ctx(ctx, f),
1297 PlaceKind::Projection(subplace, projection) => {
1298 let sub = subplace.with_ctx(ctx);
1299 match projection {
1300 ProjectionElem::Deref => {
1301 write!(f, "(*{sub})")
1302 }
1303 ProjectionElem::Field(proj_kind, field_id) => match proj_kind {
1304 FieldProjKind::Adt(adt_id, opt_variant_id) => {
1305 write!(f, "({sub}")?;
1306 if let Some(variant_id) = opt_variant_id {
1307 write!(f, " as variant ")?;
1308 ctx.format_enum_variant(f, *adt_id, *variant_id)?;
1309 }
1310 write!(f, ").")?;
1311 ctx.format_field_name(f, *adt_id, *opt_variant_id, *field_id)?;
1312 Ok(())
1313 }
1314 FieldProjKind::Tuple(_) => {
1315 write!(f, "{sub}.{field_id}")
1316 }
1317 },
1318 ProjectionElem::PtrMetadata => {
1319 write!(f, "{sub}.metadata")
1320 }
1321 ProjectionElem::Index {
1322 offset,
1323 from_end: true,
1324 ..
1325 } => write!(f, "{sub}[-{}]", offset.with_ctx(ctx)),
1326 ProjectionElem::Index {
1327 offset,
1328 from_end: false,
1329 ..
1330 } => write!(f, "{sub}[{}]", offset.with_ctx(ctx)),
1331 ProjectionElem::Subslice {
1332 from,
1333 to,
1334 from_end: true,
1335 ..
1336 } => write!(f, "{sub}[{}..-{}]", from.with_ctx(ctx), to.with_ctx(ctx)),
1337 ProjectionElem::Subslice {
1338 from,
1339 to,
1340 from_end: false,
1341 ..
1342 } => write!(f, "{sub}[{}..{}]", from.with_ctx(ctx), to.with_ctx(ctx)),
1343 }
1344 }
1345 }
1346 }
1347}
1348
1349impl<C: AstFormatter> FmtWithCtx<C> for PolyTraitDeclRef {
1350 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1351 write!(f, "{}", self.fmt_as_for(ctx))
1352 }
1353}
1354
1355impl PolyTraitDeclRef {
1356 fn fmt_trait_proof<'a, C: AstFormatter + 'a>(
1357 &'a self,
1358 id: TraitClauseId,
1359 value: Option<&'a TraitRef>,
1360 ctx: &'a C,
1361 ) -> impl Display + 'a {
1362 std::fmt::from_fn(move |f| {
1363 write!(
1364 f,
1365 "proof {}: {}",
1366 id.format_as_implied(),
1367 self.format_as_pred(ctx)
1368 )?;
1369 if let Some(value) = value {
1370 write!(f, " = {}", value.with_ctx(ctx))?;
1371 }
1372 Ok(())
1373 })
1374 }
1375
1376 fn format_as_pred<'a, C: AstFormatter + 'a>(&'a self, ctx: &'a C) -> impl Display + 'a {
1377 std::fmt::from_fn(move |f| {
1378 let ctx = &ctx.push_bound_regions(&self.regions);
1379 if !self.regions.is_empty() {
1380 let regions = self.regions.iter().map(|r| r.with_ctx(ctx));
1381 write!(f, "for<{}> ", regions.format(", "))?;
1382 }
1383 write!(f, "({})", self.skip_binder.format_as_pred(ctx))
1384 })
1385 }
1386}
1387
1388impl Display for RawAttribute {
1389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1390 write!(f, "{}", self.path)?;
1391 if let Some(args) = &self.args {
1392 write!(f, "({args})")?;
1393 }
1394 Ok(())
1395 }
1396}
1397
1398impl<C: AstFormatter> FmtWithCtx<C> for Byte {
1399 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1400 match self {
1401 Byte::Value(x) => write!(f, "{:#4x}", x),
1402 Byte::Uninit => write!(f, "--"),
1403 Byte::Provenance(p, ofs) => write!(f, "{:?}[{}]", p, ofs),
1404 }
1405 }
1406}
1407
1408impl_display_via_ctx!(ConstantExpr);
1409impl<C: AstFormatter> FmtWithCtx<C> for ConstantExpr {
1410 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1411 match &self.kind {
1412 ConstantExprKind::Literal(c) => write!(f, "{}", c),
1413 ConstantExprKind::Adt(variant_id, values) => {
1414 let values = values.iter().map(|v| v.with_ctx(ctx));
1415 match self.ty.as_adt() {
1416 Some(ty_ref) => match ty_ref.id {
1417 TypeId::Tuple => {
1418 let trailing_comma = if values.len() == 1 { "," } else { "" };
1419 let values = values.format(", ");
1420 write!(f, "({values}{trailing_comma})")
1421 }
1422 TypeId::Builtin(BuiltinTy::Box) => {
1423 let values = values.format(", ");
1424 write!(f, "Box({values})")
1425 }
1426 TypeId::Builtin(BuiltinTy::Str) => {
1427 let values = values.format(", ");
1428 write!(f, "[{values}]")
1429 }
1430 TypeId::Adt(ty_id) => {
1431 match variant_id {
1432 None => ty_id.fmt_with_ctx(ctx, f)?,
1433 Some(variant_id) => {
1434 ctx.format_enum_variant(f, ty_id, *variant_id)?
1435 }
1436 }
1437 write!(f, " {{ ")?;
1438 for (comma, (i, val)) in
1439 repeat_except_first(", ").zip(values.enumerate())
1440 {
1441 write!(f, "{}", comma.unwrap_or_default())?;
1442 let field_id = FieldId::new(i);
1443 ctx.format_field_name(f, ty_id, *variant_id, field_id)?;
1444 write!(f, ": {}", val)?;
1445 }
1446 write!(f, " }}")
1447 }
1448 },
1449 None => {
1450 let values = values.format(", ");
1451 write!(f, "ConstAdt [{values}]")
1452 }
1453 }
1454 }
1455 ConstantExprKind::Array(values) => {
1456 let values = values.iter().map(|v| v.with_ctx(ctx)).format(", ");
1457 write!(f, "[{}]", values)
1458 }
1459 ConstantExprKind::Global(global_ref) => {
1460 write!(f, "{}", global_ref.with_ctx(ctx))
1461 }
1462 ConstantExprKind::TraitConst(trait_ref, const_id) => {
1463 write!(f, "{}::", trait_ref.with_ctx(ctx),)?;
1464 ctx.format_assoc_const_name(f, trait_ref.trait_id(), *const_id)?;
1465 Ok(())
1466 }
1467 ConstantExprKind::VTableRef(trait_ref) => {
1468 write!(f, "&vtable_of({})", trait_ref.with_ctx(ctx),)
1469 }
1470 ConstantExprKind::Ref(cv, meta) => {
1471 if let Some(meta) = meta {
1472 write!(
1473 f,
1474 "&{} with_metadata({})",
1475 cv.with_ctx(ctx),
1476 meta.with_ctx(ctx)
1477 )
1478 } else {
1479 write!(f, "&{}", cv.with_ctx(ctx))
1480 }
1481 }
1482 ConstantExprKind::Ptr(rk, cv, meta) => {
1483 let rk = match rk {
1484 RefKind::Mut => "&raw mut",
1485 RefKind::Shared => "&raw const",
1486 };
1487 if let Some(meta) = meta {
1488 write!(
1489 f,
1490 "{} {} with_metadata({})",
1491 rk,
1492 cv.with_ctx(ctx),
1493 meta.with_ctx(ctx)
1494 )
1495 } else {
1496 write!(f, "{} {}", rk, cv.with_ctx(ctx))
1497 }
1498 }
1499 ConstantExprKind::Var(id) => write!(f, "{}", id.with_ctx(ctx)),
1500 ConstantExprKind::Call(fp, args) => {
1501 let args = args.iter().map(|arg| arg.with_ctx(ctx)).format(", ");
1502 write!(f, "{}({args})", fp.with_ctx(ctx))
1503 }
1504 ConstantExprKind::FnDef(fp) => {
1505 write!(f, "{}", fp.with_ctx(ctx))
1506 }
1507 ConstantExprKind::FnPtr(fp) => {
1508 write!(f, "fnptr({})", fp.with_ctx(ctx))
1509 }
1510 ConstantExprKind::TypeId(ty) => {
1511 write!(f, "TypeId({})", ty.with_ctx(ctx))
1512 }
1513 ConstantExprKind::PtrNoProvenance(v) => write!(f, "no-provenance {v}"),
1514 ConstantExprKind::RawMemory(bytes) => {
1515 let bytes = bytes.iter().map(|v| v.with_ctx(ctx)).format(", ");
1516 write!(f, "RawMemory({})", bytes)
1517 }
1518 ConstantExprKind::Opaque(cause) => write!(f, "Opaque({cause})"),
1519 }
1520 }
1521}
1522
1523impl<C: AstFormatter> FmtWithCtx<C> for Region {
1524 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1525 match self {
1526 Region::Static => write!(f, "'static"),
1527 Region::Var(var) => write!(f, "{}", var.with_ctx(ctx)),
1528 Region::Body(id) => write!(f, "'{}", id),
1529 Region::Erased => write!(f, "'_"),
1530 }
1531 }
1532}
1533
1534impl<T> RegionBinder<T> {
1535 fn fmt_split<'a, C>(&'a self, ctx: &'a C) -> (String, String)
1537 where
1538 C: AstFormatter,
1539 T: FmtWithCtx<C::Reborrow<'a>>,
1540 {
1541 self.fmt_split_with(ctx, |ctx, x| x.to_string_with_ctx(ctx))
1542 }
1543 fn fmt_split_with<'a, C>(
1545 &'a self,
1546 ctx: &'a C,
1547 fmt_inner: impl FnOnce(&C::Reborrow<'a>, &T) -> String,
1548 ) -> (String, String)
1549 where
1550 C: AstFormatter,
1551 {
1552 let ctx = &ctx.push_bound_regions(&self.regions);
1553 (
1554 self.regions
1555 .iter()
1556 .map(|r| r.with_ctx(ctx))
1557 .format(", ")
1558 .to_string(),
1559 fmt_inner(ctx, &self.skip_binder),
1560 )
1561 }
1562
1563 fn fmt_as_for<'a, C>(&'a self, ctx: &'a C) -> String
1565 where
1566 C: AstFormatter,
1567 T: FmtWithCtx<C::Reborrow<'a>>,
1568 {
1569 self.fmt_as_for_with(ctx, |ctx, x| x.to_string_with_ctx(ctx))
1570 }
1571 fn fmt_as_for_with<'a, C>(
1573 &'a self,
1574 ctx: &'a C,
1575 fmt_inner: impl FnOnce(&C::Reborrow<'a>, &T) -> String,
1576 ) -> String
1577 where
1578 C: AstFormatter,
1579 T: FmtWithCtx<C::Reborrow<'a>>,
1580 {
1581 let (regions, value) = self.fmt_split_with(ctx, fmt_inner);
1582 let regions = if regions.is_empty() {
1583 "".to_string()
1584 } else {
1585 format!("for<{regions}> ",)
1586 };
1587 format!("{regions}{value}",)
1588 }
1589}
1590
1591impl<C: AstFormatter> FmtWithCtx<C> for RegionDbVar {
1592 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1593 ctx.format_bound_var(f, *self, "'_", |v| {
1594 v.name.as_ref().map(|name| name.to_string())
1595 })
1596 }
1597}
1598
1599impl<C: AstFormatter> FmtWithCtx<C> for RegionParam {
1600 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1601 if self.mutability.is_mutable() {
1602 write!(f, "mut ")?;
1603 }
1604 match &self.name {
1605 Some(name) => write!(f, "{name}"),
1606 None => {
1607 write!(f, "'_{}", self.index)?;
1608 if let Some(d @ 1..) = ctx.binder_depth().checked_sub(1) {
1609 write!(f, "_{d}")?;
1610 }
1611 Ok(())
1612 }
1613 }
1614 }
1615}
1616
1617impl_display_via_ctx!(Rvalue);
1618impl<C: AstFormatter> FmtWithCtx<C> for Rvalue {
1619 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1620 match self {
1621 Rvalue::Use(x, _) => write!(f, "{}", x.with_ctx(ctx)),
1622 Rvalue::Ref {
1623 place,
1624 kind: borrow_kind,
1625 ptr_metadata,
1626 } => {
1627 let borrow_kind = match borrow_kind {
1628 BorrowKind::Shared => "&",
1629 BorrowKind::Mut => "&mut ",
1630 BorrowKind::TwoPhaseMut => "&two-phase-mut ",
1631 BorrowKind::UniqueImmutable => "&uniq ",
1632 BorrowKind::Shallow => "&shallow ",
1633 };
1634 if ptr_metadata.ty().is_unit() {
1635 write!(f, "{borrow_kind}{}", place.with_ctx(ctx))?;
1637 } else {
1638 write!(
1639 f,
1640 "{borrow_kind}{} with_metadata({})",
1641 place.with_ctx(ctx),
1642 ptr_metadata.with_ctx(ctx)
1643 )?;
1644 }
1645 Ok(())
1646 }
1647 Rvalue::RawPtr {
1648 place,
1649 kind: mutability,
1650 ptr_metadata,
1651 } => {
1652 let ptr_kind = match mutability {
1653 RefKind::Shared => "&raw const ",
1654 RefKind::Mut => "&raw mut ",
1655 };
1656 if ptr_metadata.ty().is_unit() {
1657 write!(f, "{ptr_kind}{}", place.with_ctx(ctx))?;
1659 } else {
1660 write!(
1661 f,
1662 "{ptr_kind}{} with_metadata({})",
1663 place.with_ctx(ctx),
1664 ptr_metadata.with_ctx(ctx)
1665 )?;
1666 }
1667 Ok(())
1668 }
1669
1670 Rvalue::BinaryOp(binop, x, y) => {
1671 write!(f, "{} {} {}", x.with_ctx(ctx), binop, y.with_ctx(ctx))
1672 }
1673 Rvalue::UnaryOp(unop, x) => {
1674 write!(f, "{}({})", unop.with_ctx(ctx), x.with_ctx(ctx))
1675 }
1676 Rvalue::NullaryOp(op, ty) => {
1677 write!(f, "{}<{}>", op.with_ctx(ctx), ty.with_ctx(ctx))
1678 }
1679 Rvalue::Discriminant(p) => {
1680 write!(f, "@discriminant({})", p.with_ctx(ctx),)
1681 }
1682 Rvalue::Aggregate(kind, ops) => {
1683 let ops_s = ops.iter().map(|op| op.with_ctx(ctx)).format(", ");
1684 match kind {
1685 AggregateKind::Adt(ty_ref, variant_id, field_id) => {
1686 match ty_ref.id {
1687 TypeId::Tuple => {
1688 let trailing_comma = if ops.len() == 1 { "," } else { "" };
1689 write!(f, "({ops_s}{trailing_comma})")
1690 }
1691 TypeId::Builtin(BuiltinTy::Box) => write!(f, "Box({})", ops_s),
1692 TypeId::Builtin(BuiltinTy::Str) => {
1693 write!(f, "[{}]", ops_s)
1694 }
1695 TypeId::Adt(ty_id) => {
1696 match variant_id {
1697 None => ty_id.fmt_with_ctx(ctx, f)?,
1698 Some(variant_id) => {
1699 ctx.format_enum_variant(f, ty_id, *variant_id)?
1700 }
1701 }
1702 write!(f, " {{ ")?;
1703 for (comma, (i, op)) in
1704 repeat_except_first(", ").zip(ops.iter().enumerate())
1705 {
1706 write!(f, "{}", comma.unwrap_or_default())?;
1707 let field_id = match *field_id {
1708 None => FieldId::new(i),
1709 Some(field_id) => {
1710 assert_eq!(i, 0); field_id
1712 }
1713 };
1714 ctx.format_field_name(f, ty_id, *variant_id, field_id)?;
1715 write!(f, ": {}", op.with_ctx(ctx))?;
1716 }
1717 write!(f, " }}")
1718 }
1719 }
1720 }
1721 AggregateKind::Array(..) => {
1722 write!(f, "[{}]", ops_s)
1723 }
1724 AggregateKind::RawPtr(_, rmut) => {
1725 let mutability = match rmut {
1726 RefKind::Shared => "const",
1727 RefKind::Mut => "mut ",
1728 };
1729 write!(f, "*{} ({})", mutability, ops_s)
1730 }
1731 }
1732 }
1733 Rvalue::Len(place, ..) => write!(f, "len({})", place.with_ctx(ctx)),
1734 Rvalue::Repeat(op, _ty, cg) => {
1735 write!(f, "[{}; {}]", op.with_ctx(ctx), cg.with_ctx(ctx))
1736 }
1737 }
1738 }
1739}
1740
1741impl Display for ScalarValue {
1742 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
1743 match self {
1744 ScalarValue::Signed(ty, v) => write!(f, "{v}{ty}"),
1745 ScalarValue::Unsigned(ty, v) => write!(f, "{v}{ty}"),
1746 }
1747 }
1748}
1749
1750impl<C: AstFormatter> FmtWithCtx<C> for ullbc::Statement {
1751 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1752 let tab = ctx.indent();
1753 use ullbc::StatementKind;
1754 for line in &self.comments_before {
1755 writeln!(f, "{tab}// {line}")?;
1756 }
1757 match &self.kind {
1758 StatementKind::Assign(place, rvalue) => {
1759 write!(f, "{tab}{} = {}", place.with_ctx(ctx), rvalue.with_ctx(ctx),)
1760 }
1761 StatementKind::SetDiscriminant(place, variant_id) => write!(
1762 f,
1763 "{tab}@discriminant({}) = {}",
1764 place.with_ctx(ctx),
1765 variant_id
1766 ),
1767 StatementKind::CopyNonOverlapping(cno) => {
1768 write!(
1769 f,
1770 "{}copy_nonoverlapping({}, {}, {})",
1771 tab,
1772 cno.src.with_ctx(ctx),
1773 cno.dst.with_ctx(ctx),
1774 cno.count.with_ctx(ctx),
1775 )
1776 }
1777 StatementKind::StorageLive(var_id) => {
1778 write!(f, "{tab}storage_live({})", var_id.with_ctx(ctx))
1779 }
1780 StatementKind::StorageDead(var_id) => {
1781 write!(f, "{tab}storage_dead({})", var_id.with_ctx(ctx))
1782 }
1783 StatementKind::PlaceMention(place) => {
1784 write!(f, "{tab}_ = {}", place.with_ctx(ctx))
1785 }
1786 StatementKind::Assert { assert, on_failure } => {
1787 write!(
1788 f,
1789 "{tab}{} else {}",
1790 assert.with_ctx(ctx),
1791 on_failure.with_ctx(ctx)
1792 )
1793 }
1794 StatementKind::Nop => write!(f, "{tab}nop"),
1795 }
1796 }
1797}
1798
1799impl<C: AstFormatter> FmtWithCtx<C> for llbc::Statement {
1800 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1801 let tab = ctx.indent();
1802 use llbc::StatementKind;
1803 for line in &self.comments_before {
1804 writeln!(f, "{tab}// {line}")?;
1805 }
1806 write!(f, "{tab}")?;
1807 match &self.kind {
1808 StatementKind::Assign(place, rvalue) => {
1809 write!(f, "{} = {}", place.with_ctx(ctx), rvalue.with_ctx(ctx),)
1810 }
1811 StatementKind::SetDiscriminant(place, variant_id) => {
1812 write!(f, "@discriminant({}) = {}", place.with_ctx(ctx), variant_id)
1813 }
1814 StatementKind::CopyNonOverlapping(cno) => {
1815 write!(
1816 f,
1817 "copy_nonoverlapping({}, {}, {})",
1818 cno.src.with_ctx(ctx),
1819 cno.dst.with_ctx(ctx),
1820 cno.count.with_ctx(ctx),
1821 )
1822 }
1823 StatementKind::StorageLive(var_id) => {
1824 write!(f, "storage_live({})", var_id.with_ctx(ctx))
1825 }
1826 StatementKind::StorageDead(var_id) => {
1827 write!(f, "storage_dead({})", var_id.with_ctx(ctx))
1828 }
1829 StatementKind::PlaceMention(place) => {
1830 write!(f, "_ = {}", place.with_ctx(ctx))
1831 }
1832 StatementKind::Drop(place, tref, kind) => {
1833 let kind = match kind {
1834 DropKind::Precise => "drop",
1835 DropKind::Conditional => "conditional_drop",
1836 };
1837 write!(f, "{kind}[{}] {}", tref.with_ctx(ctx), place.with_ctx(ctx),)
1838 }
1839 StatementKind::Assert { assert, on_failure } => {
1840 write!(
1841 f,
1842 "{} else {}",
1843 assert.with_ctx(ctx),
1844 on_failure.with_ctx(ctx)
1845 )
1846 }
1847 StatementKind::InlineAsm { asm, targets } => {
1848 write!(f, "asm!({asm:?})")?;
1849 if let [target] = targets.as_slice() {
1850 for statement in &target.statements {
1851 write!(f, "\n{}", statement.with_ctx(ctx))?;
1852 }
1853 return Ok(());
1854 }
1855 if !targets.is_empty() {
1856 write!(f, " {{")?;
1857 let ctx1 = &ctx.increase_indent();
1858 let tab1 = ctx1.indent();
1859 let ctx2 = &ctx1.increase_indent();
1860 for (i, target) in targets.iter().enumerate() {
1861 write!(
1862 f,
1863 "\n{tab1}target {i} => {{\n{}{tab1}}}",
1864 target.with_ctx(ctx2)
1865 )?;
1866 }
1867 write!(f, "\n{tab}}}")?;
1868 }
1869 Ok(())
1870 }
1871 StatementKind::Call(call) => {
1872 write!(f, "{}", call.with_ctx(ctx))
1873 }
1874 StatementKind::Abort(kind) => {
1875 write!(f, "{}", kind.with_ctx(ctx))
1876 }
1877 StatementKind::Return => write!(f, "return"),
1878 StatementKind::Break(index) => write!(f, "break {index}"),
1879 StatementKind::Continue(index) => write!(f, "continue {index}"),
1880 StatementKind::Nop => write!(f, "nop"),
1881 StatementKind::Switch(switch) => match switch {
1882 Switch::If(discr, true_st, false_st) => {
1883 let ctx = &ctx.increase_indent();
1884 write!(
1885 f,
1886 "if {} {{\n{}{tab}}} else {{\n{}{tab}}}",
1887 discr.with_ctx(ctx),
1888 true_st.with_ctx(ctx),
1889 false_st.with_ctx(ctx),
1890 )
1891 }
1892 Switch::SwitchInt(discr, _ty, maps, otherwise) => {
1893 writeln!(f, "switch {} {{", discr.with_ctx(ctx))?;
1894 let ctx1 = &ctx.increase_indent();
1895 let inner_tab1 = ctx1.indent();
1896 let ctx2 = &ctx1.increase_indent();
1897 for (pvl, st) in maps {
1898 let pvl = pvl.iter().format(" | ");
1900 writeln!(
1901 f,
1902 "{inner_tab1}{} => {{\n{}{inner_tab1}}},",
1903 pvl,
1904 st.with_ctx(ctx2),
1905 )?;
1906 }
1907 writeln!(
1908 f,
1909 "{inner_tab1}_ => {{\n{}{inner_tab1}}},",
1910 otherwise.with_ctx(ctx2),
1911 )?;
1912 write!(f, "{tab}}}")
1913 }
1914 Switch::Match(discr, maps, otherwise) => {
1915 writeln!(f, "match {} {{", discr.with_ctx(ctx))?;
1916 let ctx1 = &ctx.increase_indent();
1917 let inner_tab1 = ctx1.indent();
1918 let ctx2 = &ctx1.increase_indent();
1919 let discr_type: Option<TypeDeclId> = discr
1920 .ty
1921 .kind()
1922 .as_adt()
1923 .and_then(|tref| tref.id.as_adt())
1924 .copied();
1925 for (cases, st) in maps {
1926 write!(f, "{inner_tab1}",)?;
1927 for (bar, v) in repeat_except_first(" | ").zip(cases.iter()) {
1929 write!(f, "{}", bar.unwrap_or_default())?;
1930 match discr_type {
1931 Some(type_id) => ctx.format_enum_variant(f, type_id, *v)?,
1932 None => write!(f, "{}", v.to_pretty_string())?,
1933 }
1934 }
1935 writeln!(f, " => {{\n{}{inner_tab1}}},", st.with_ctx(ctx2),)?;
1936 }
1937 if let Some(otherwise) = otherwise {
1938 writeln!(
1939 f,
1940 "{inner_tab1}_ => {{\n{}{inner_tab1}}},",
1941 otherwise.with_ctx(ctx2),
1942 )?;
1943 }
1944 write!(f, "{tab}}}")
1945 }
1946 },
1947 StatementKind::Loop(body) => {
1948 let ctx = &ctx.increase_indent();
1949 write!(f, "loop {{\n{}{tab}}}", body.with_ctx(ctx))
1950 }
1951 StatementKind::Error(s) => write!(f, "@ERROR({})", s),
1952 }
1953 }
1954}
1955
1956impl<C: AstFormatter> FmtWithCtx<C> for Terminator {
1957 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1958 let tab = ctx.indent();
1959 for line in &self.comments_before {
1960 writeln!(f, "{tab}// {line}")?;
1961 }
1962 write!(f, "{tab}")?;
1963 match &self.kind {
1964 TerminatorKind::Goto { target } => write!(f, "goto bb{target}"),
1965 TerminatorKind::Switch { discr, targets } => match targets {
1966 SwitchTargets::If(true_block, false_block) => write!(
1967 f,
1968 "if {} -> bb{} else -> bb{}",
1969 discr.with_ctx(ctx),
1970 true_block,
1971 false_block
1972 ),
1973 SwitchTargets::SwitchInt(_ty, maps, otherwise) => {
1974 let maps = maps
1975 .iter()
1976 .map(|(v, bid)| format!("{}: bb{}", v, bid))
1977 .chain([format!("otherwise: bb{otherwise}")])
1978 .format(", ");
1979 write!(f, "switch {} -> {}", discr.with_ctx(ctx), maps)
1980 }
1981 },
1982 TerminatorKind::Call {
1983 call,
1984 target,
1985 on_unwind,
1986 } => {
1987 let call = call.with_ctx(ctx);
1988 write!(f, "{call} -> bb{target} (unwind: bb{on_unwind})",)
1989 }
1990 TerminatorKind::Drop {
1991 kind,
1992 place,
1993 fn_ptr,
1994 target,
1995 on_unwind,
1996 } => {
1997 let kind = match kind {
1998 DropKind::Precise => "drop",
1999 DropKind::Conditional => "conditional_drop",
2000 };
2001 write!(
2002 f,
2003 "{kind}[{}] {} -> bb{target} (unwind: bb{on_unwind})",
2004 fn_ptr.with_ctx(ctx),
2005 place.with_ctx(ctx),
2006 )
2007 }
2008 TerminatorKind::Assert {
2009 assert,
2010 target,
2011 on_unwind,
2012 } => {
2013 write!(
2014 f,
2015 "assert {} -> bb{target} (unwind: bb{on_unwind})",
2016 assert.with_ctx(ctx),
2017 )
2018 }
2019 TerminatorKind::InlineAsm {
2020 asm,
2021 targets,
2022 on_unwind,
2023 } => {
2024 let targets = targets
2025 .iter()
2026 .enumerate()
2027 .map(|(i, target)| format!("target {i}: bb{target}"))
2028 .chain([format!("unwind: bb{on_unwind}")])
2029 .format(", ");
2030 write!(f, "asm!({asm:?}) -> {targets}")
2031 }
2032 TerminatorKind::Abort(kind) => write!(f, "{}", kind.with_ctx(ctx)),
2033 TerminatorKind::Return => write!(f, "return"),
2034 TerminatorKind::UnwindResume => write!(f, "unwind_continue"),
2035 }
2036 }
2037}
2038
2039impl<C: AstFormatter> FmtWithCtx<C> for TraitParam {
2040 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2041 write!(f, "{}", self.clause_id.format_as_required())?;
2042 if let Some(d @ 1..) = ctx.binder_depth().checked_sub(1) {
2043 write!(f, "_{d}")?;
2044 }
2045 write!(f, ": {}", self.trait_.format_as_pred(ctx))
2046 }
2047}
2048
2049impl TraitClauseId {
2050 pub(crate) fn format_as_implied(self) -> impl Display {
2051 std::fmt::from_fn(move |f| write!(f, "ImpliedClause{self}"))
2052 }
2053
2054 pub(crate) fn format_as_required(self) -> impl Display {
2055 std::fmt::from_fn(move |f| write!(f, "TraitClause{self}"))
2056 }
2057}
2058
2059impl<C: AstFormatter> FmtWithCtx<C> for TraitDecl {
2060 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2061 let ctx = &ctx.set_generics(&self.generics);
2063
2064 self.item_meta
2065 .fmt_item_intro(f, ctx, "trait", self.def_id)?;
2066
2067 let (generics, clauses) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
2068 write!(f, "{generics}{clauses}")?;
2069
2070 let any_item = !self.implied_clauses.is_empty()
2071 || !self.consts.is_empty()
2072 || !self.types.is_empty()
2073 || !self.methods.is_empty();
2074 if any_item {
2075 write!(f, "\n{{\n")?;
2076 for c in &self.implied_clauses {
2077 writeln!(
2078 f,
2079 "{TAB_INCR}{}",
2080 c.trait_.fmt_trait_proof(c.clause_id, None, ctx)
2081 )?;
2082 }
2083 for assoc_const in &self.consts {
2084 let name = &assoc_const.name;
2085 let ty = assoc_const.ty.with_ctx(ctx);
2086 writeln!(f, "{TAB_INCR}const {name} : {ty}")?;
2087 }
2088 for assoc_ty in &self.types {
2089 let name = assoc_ty.name();
2090 let ctx = &ctx.push_binder(Cow::Borrowed(&assoc_ty.params));
2091 let clauses = assoc_ty
2092 .params
2093 .formatted_clauses(ctx)
2094 .map(|x| x.to_string())
2095 .chain(assoc_ty.skip_binder.implied_clauses.iter().map(|clause| {
2096 clause
2097 .trait_
2098 .fmt_trait_proof(clause.clause_id, None, ctx)
2099 .to_string()
2100 }));
2101 let params = if assoc_ty.params.has_explicits() {
2102 format!("<{}>", assoc_ty.params.formatted_params(ctx).format(", "))
2103 } else {
2104 String::new()
2105 };
2106 write!(f, "{TAB_INCR}type {name}{params}")?;
2107 if let Some(default) = &assoc_ty.skip_binder.default {
2108 write!(f, " = {}", default.value.with_ctx(ctx))?;
2109 }
2110 write!(f, "{}", fmt_where_clauses(clauses, TAB_INCR))?;
2111 writeln!(f)?;
2112 }
2113 for method in self.methods() {
2114 let name = method.name();
2115 let (params, fn_ref) =
2116 method.fmt_split_with(ctx, |ctx, method| method.item.to_string_with_ctx(ctx));
2117 writeln!(f, "{TAB_INCR}fn {name}{params} = {fn_ref}")?;
2118 }
2119 if let Some(vtb_ref) = &self.vtable {
2120 writeln!(f, "{TAB_INCR}vtable: {}", vtb_ref.with_ctx(ctx))?;
2121 } else {
2122 writeln!(f, "{TAB_INCR}non-dyn-compatible")?;
2123 }
2124 write!(f, "}}")?;
2125 }
2126 Ok(())
2127 }
2128}
2129
2130impl<C: AstFormatter> FmtWithCtx<C> for TraitDeclId {
2131 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2132 ItemId::from(*self).fmt_with_ctx(ctx, f)
2133 }
2134}
2135
2136impl<C: AstFormatter> FmtWithCtx<C> for TraitDeclRef {
2137 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2138 let trait_id = self.id.with_ctx(ctx);
2139 let generics = self.generics.with_ctx(ctx);
2140 write!(f, "{trait_id}{generics}")
2141 }
2142}
2143
2144impl TraitDeclRef {
2145 pub fn split_self(&self) -> (Option<Ty>, Self) {
2148 let mut pred = self.clone();
2149 let self_ty = pred.generics.types.remove_and_shift_ids(TypeVarId::ZERO);
2150 (self_ty, pred)
2151 }
2152
2153 fn format_as_pred<'a, C: AstFormatter + 'a>(&'a self, ctx: &'a C) -> impl Display + 'a {
2154 std::fmt::from_fn(move |f| {
2155 let (self_ty, pred) = self.split_self();
2156 match self_ty {
2157 Some(self_ty) => write!(f, "{}: {}", self_ty.with_ctx(ctx), pred.with_ctx(ctx)),
2158 None => write!(f, "{}", pred.with_ctx(ctx)),
2160 }
2161 })
2162 }
2163
2164 fn format_as_impl<'a, C: AstFormatter>(&'a self, ctx: &'a C) -> impl Display + 'a {
2165 std::fmt::from_fn(move |f| {
2166 let (self_ty, pred) = self.split_self();
2167 match self_ty {
2168 Some(self_ty) => write!(f, "{} for {}", pred.with_ctx(ctx), self_ty.with_ctx(ctx)),
2169 None => write!(f, "{}", pred.with_ctx(ctx)),
2171 }
2172 })
2173 }
2174}
2175
2176impl<C: AstFormatter> FmtWithCtx<C> for TraitImpl {
2177 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2178 let trait_id = self.impl_trait.id;
2179 writeln!(f, "// Full name: {}", self.item_meta.name.full_name(ctx))?;
2180
2181 let ctx = &ctx.set_generics(&self.generics);
2183
2184 let (generics, clauses) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
2185 let impl_trait = self.impl_trait.format_as_impl(ctx);
2186 write!(f, "impl{generics}")?;
2187 if let Some(short_name) = trait_impl_short_name(ctx, self.def_id) {
2188 write!(f, " \"{}\"", short_name.with_ctx(ctx))?;
2189 }
2190 write!(f, " {impl_trait}{clauses}",)?;
2191
2192 let newline = if clauses.is_empty() {
2193 " ".to_string()
2194 } else {
2195 "\n".to_string()
2196 };
2197 writeln!(f, "{newline}{{")?;
2198
2199 let any_item = !self.implied_trait_refs.is_empty()
2200 || !self.consts.is_empty()
2201 || !self.types.is_empty()
2202 || !self.methods.is_empty();
2203 if any_item {
2204 for (id, trait_ref) in self.implied_trait_refs.iter_enumerated() {
2205 writeln!(
2206 f,
2207 "{TAB_INCR}{}",
2208 trait_ref
2209 .trait_decl_ref
2210 .fmt_trait_proof(id, Some(trait_ref), ctx)
2211 )?;
2212 }
2213 for (const_id, global) in self.consts.iter_enumerated() {
2214 write!(f, "{TAB_INCR}const ")?;
2215 ctx.format_assoc_const_name(f, trait_id, const_id)?;
2216 writeln!(f, " = {}", global.with_ctx(ctx))?;
2217 }
2218 for (type_id, assoc_ty) in self.types.iter_enumerated() {
2219 let ctx = &ctx.push_binder(Cow::Borrowed(&assoc_ty.params));
2220 let params = if assoc_ty.params.has_explicits() {
2221 format!("<{}>", assoc_ty.params.formatted_params(ctx).format(", "))
2222 } else {
2223 String::new()
2224 };
2225 let ty = assoc_ty.skip_binder.value.with_ctx(ctx);
2226 let clauses = assoc_ty
2227 .params
2228 .formatted_clauses(ctx)
2229 .map(|x| x.to_string())
2230 .chain(
2231 assoc_ty
2232 .skip_binder
2233 .implied_trait_refs
2234 .iter_enumerated()
2235 .map(|(id, trait_ref)| {
2236 trait_ref
2237 .trait_decl_ref
2238 .fmt_trait_proof(id, Some(trait_ref), ctx)
2239 .to_string()
2240 }),
2241 );
2242 write!(f, "{TAB_INCR}type ")?;
2243 ctx.format_assoc_type_name(f, trait_id, type_id)?;
2244 write!(f, "{params} = {ty}")?;
2245 write!(f, "{}", fmt_where_clauses(clauses, TAB_INCR))?;
2246 writeln!(f)?;
2247 }
2248 for (method_id, bound_fn) in self.methods.iter_enumerated() {
2249 let (params, fn_ref) = bound_fn.fmt_split(ctx);
2250 write!(f, "{TAB_INCR}fn ")?;
2251 ctx.format_method_name(f, trait_id, method_id)?;
2252 writeln!(f, "{params} = {fn_ref}")?;
2253 }
2254 }
2255 if let Some(vtb_ref) = &self.vtable {
2256 writeln!(f, "{TAB_INCR}vtable: {}", vtb_ref.with_ctx(ctx))?;
2257 } else {
2258 writeln!(f, "{TAB_INCR}non-dyn-compatible")?;
2259 }
2260 write!(f, "}}")?;
2261 Ok(())
2262 }
2263}
2264
2265impl<C: AstFormatter> FmtWithCtx<C> for TraitImplId {
2266 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2267 ItemId::from(*self).fmt_with_ctx(ctx, f)
2268 }
2269}
2270
2271impl<C: AstFormatter> FmtWithCtx<C> for TraitImplRef {
2272 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2273 let id = self.id.with_ctx(ctx);
2274 let generics = self.generics.with_ctx(ctx);
2275 write!(f, "{id}{generics}")
2276 }
2277}
2278
2279impl Display for TraitItemName {
2280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
2281 write!(f, "{}", self.0)
2282 }
2283}
2284
2285impl<C: AstFormatter> FmtWithCtx<C> for TraitRef {
2286 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2287 match &self.kind {
2288 TraitRefKind::SelfId => write!(f, "Self"),
2289 TraitRefKind::ParentClause(sub, clause_id) => {
2290 let sub = sub.with_ctx(ctx);
2291 write!(f, "{sub}::{}", clause_id.format_as_implied())
2292 }
2293 TraitRefKind::ItemClause(sub, type_id, clause_id) => {
2294 write!(f, "{}::", sub.with_ctx(ctx))?;
2295 ctx.format_assoc_type_name(f, sub.trait_id(), *type_id)?;
2296 write!(f, "::{}", clause_id.format_as_implied())
2297 }
2298 TraitRefKind::TraitImpl(impl_ref) => {
2299 write!(f, "{}", impl_ref.with_ctx(ctx))
2300 }
2301 TraitRefKind::Clause(id) => write!(f, "{}", id.with_ctx(ctx)),
2302 TraitRefKind::BuiltinOrAuto { types, .. } => {
2303 let bound_ctx = &ctx.push_bound_regions(&self.trait_decl_ref.regions);
2304 let impl_trait = self.trait_decl_ref.skip_binder.format_as_impl(bound_ctx);
2305 write!(f, "{{built_in impl {impl_trait}")?;
2306 if !types.is_empty() {
2307 let trait_id = self.trait_decl_ref.skip_binder.id;
2308 let types = types
2309 .iter_indexed()
2310 .map(|(type_id, assoc_ty)| {
2311 std::fmt::from_fn(move |f| {
2312 ctx.format_assoc_type_name(f, trait_id, type_id)?;
2313 let ty = assoc_ty.value.with_ctx(ctx);
2314 write!(f, " = {ty}")
2315 })
2316 })
2317 .join(", ");
2318 write!(f, " where {types}")?;
2319 }
2320 write!(f, "}}")?;
2321 Ok(())
2322 }
2323 TraitRefKind::Dyn => write!(f, "{}", self.trait_decl_ref.with_ctx(ctx)),
2324 TraitRefKind::Unknown(msg) => write!(f, "UNKNOWN({msg})"),
2325 }
2326 }
2327}
2328
2329impl<C: AstFormatter> FmtWithCtx<C> for TraitTypeConstraint {
2330 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2331 let trait_ref = self.trait_ref.with_ctx(ctx);
2332 let ty = self.ty.with_ctx(ctx);
2333 write!(f, "{trait_ref}::")?;
2334 ctx.format_assoc_type_name(f, self.trait_ref.trait_id(), self.type_id)?;
2335 write!(f, " = {ty}")
2336 }
2337}
2338
2339impl<C: AstFormatter> FmtWithCtx<C> for Ty {
2340 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2341 match self.kind() {
2342 TyKind::Adt(tref) => match tref.id {
2343 TypeId::Tuple => {
2344 let generics = tref.generics.fmt_explicits(ctx).format(", ");
2345 let trailing_comma = if tref.generics.types.len() == 1 {
2346 ","
2347 } else {
2348 ""
2349 };
2350 write!(f, "({generics}{trailing_comma})")
2351 }
2352 _ => write!(f, "{}", tref.with_ctx(ctx)),
2353 },
2354 TyKind::TypeVar(id) => write!(f, "{}", id.with_ctx(ctx)),
2355 TyKind::Literal(kind) => write!(f, "{kind}"),
2356 TyKind::Never => write!(f, "!"),
2357 TyKind::Pattern(ty, pat) => write!(f, "{} is {}", ty.with_ctx(ctx), pat.with_ctx(ctx)),
2358 TyKind::Ref(r, ty, kind) => {
2359 write!(f, "&{} ", r.with_ctx(ctx))?;
2360 if let RefKind::Mut = kind {
2361 write!(f, "mut ")?;
2362 }
2363 write!(f, "{}", ty.with_ctx(ctx))
2364 }
2365 TyKind::RawPtr(ty, kind) => {
2366 write!(f, "*")?;
2367 match kind {
2368 RefKind::Shared => write!(f, "const")?,
2369 RefKind::Mut => write!(f, "mut")?,
2370 }
2371 write!(f, " {}", ty.with_ctx(ctx))
2372 }
2373 TyKind::Array(ty, len) => {
2374 write!(f, "[{}; {}]", ty.with_ctx(ctx), len.with_ctx(ctx))
2375 }
2376 TyKind::Slice(ty) => {
2377 write!(f, "[{}]", ty.with_ctx(ctx))
2378 }
2379 TyKind::TraitType(trait_ref, type_id, generics) => {
2380 write!(f, "{}::", trait_ref.with_ctx(ctx))?;
2381 ctx.format_assoc_type_name(f, trait_ref.trait_id(), *type_id)?;
2382 write!(f, "{}", generics.with_ctx(ctx))
2383 }
2384 TyKind::DynTrait(pred) => {
2385 write!(f, "(dyn {})", pred.with_ctx(ctx))
2386 }
2387 TyKind::FnPtr(io) => {
2388 write!(f, "{}", io.with_ctx(ctx))
2389 }
2390 TyKind::FnDef(binder) => {
2391 let (regions, value) = binder.fmt_split(ctx);
2392 if !regions.is_empty() {
2393 write!(f, "for<{regions}> ",)?
2394 };
2395 write!(f, "{value}",)
2396 }
2397 TyKind::PtrMetadata(ty) => {
2398 write!(f, "PtrMetadata<{}>", ty.with_ctx(ctx))
2399 }
2400 TyKind::Error(msg) => write!(f, "type_error(\"{msg}\")"),
2401 }
2402 }
2403}
2404
2405impl<C: AstFormatter> FmtWithCtx<C> for TypePattern {
2406 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2407 match self {
2408 TypePattern::Range(start, end) => {
2409 write!(f, "{}..={}", start.with_ctx(ctx), end.with_ctx(ctx))
2410 }
2411 TypePattern::OrPattern(patterns) => {
2412 write!(
2413 f,
2414 "({})",
2415 patterns.iter().map(|pat| pat.with_ctx(ctx)).format(" | ")
2416 )
2417 }
2418 TypePattern::NotNull => write!(f, "!null"),
2419 }
2420 }
2421}
2422
2423impl<C: AstFormatter> FmtWithCtx<C> for TypeDbVar {
2424 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2425 ctx.format_bound_var(f, *self, "@Type", |v| Some(v.name.clone()))
2426 }
2427}
2428
2429impl<C: AstFormatter> FmtWithCtx<C> for TypeDecl {
2430 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2431 let keyword = match &self.kind {
2432 TypeDeclKind::Struct(..) => "struct",
2433 TypeDeclKind::Union(..) => "union",
2434 TypeDeclKind::Enum(..) => "enum",
2435 TypeDeclKind::Alias(..) => "type",
2436 TypeDeclKind::Opaque | TypeDeclKind::Error(..) => "opaque type",
2437 };
2438 self.item_meta
2439 .fmt_item_intro(f, ctx, keyword, self.def_id)?;
2440
2441 let ctx = &ctx.set_generics(&self.generics);
2442 let (params, preds) = self.generics.fmt_with_ctx_with_trait_clauses(ctx);
2443 write!(f, "{params}{preds}")?;
2444
2445 let nl_or_space = if !self.generics.has_predicates() {
2446 " ".to_string()
2447 } else {
2448 "\n".to_string()
2449 };
2450 match &self.kind {
2451 TypeDeclKind::Struct(fields) => {
2452 write!(f, "{nl_or_space}{{")?;
2453 if !fields.is_empty() {
2454 writeln!(f)?;
2455 for field in fields {
2456 writeln!(f, " {},", field.with_ctx(ctx))?;
2457 }
2458 }
2459 write!(f, "}}")
2460 }
2461 TypeDeclKind::Union(fields) => {
2462 write!(f, "{nl_or_space}{{")?;
2463 writeln!(f)?;
2464 for field in fields {
2465 writeln!(f, " {},", field.with_ctx(ctx))?;
2466 }
2467 write!(f, "}}")
2468 }
2469 TypeDeclKind::Enum(variants) => {
2470 write!(f, "{nl_or_space}{{")?;
2471 writeln!(f)?;
2472 for variant in variants {
2473 writeln!(f, " {},", variant.with_ctx(ctx))?;
2474 }
2475 write!(f, "}}")
2476 }
2477 TypeDeclKind::Alias(ty) => write!(f, " = {}", ty.with_ctx(ctx)),
2478 TypeDeclKind::Opaque => write!(f, ""),
2479 TypeDeclKind::Error(msg) => write!(f, " = ERROR({msg})"),
2480 }
2481 }
2482}
2483
2484impl<C: AstFormatter> FmtWithCtx<C> for TypeDeclId {
2485 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2486 ItemId::from(*self).fmt_with_ctx(ctx, f)
2487 }
2488}
2489
2490impl<C: AstFormatter> FmtWithCtx<C> for TypeDeclRef {
2491 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2492 let id = self.id.with_ctx(ctx);
2493 let generics = self.generics.with_ctx(ctx);
2494 write!(f, "{id}{generics}")
2495 }
2496}
2497
2498impl<C: AstFormatter> FmtWithCtx<C> for TypeId {
2499 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2500 match self {
2501 TypeId::Tuple => Ok(()),
2502 TypeId::Adt(def_id) => write!(f, "{}", def_id.with_ctx(ctx)),
2503 TypeId::Builtin(aty) => write!(f, "{}", aty.get_name().with_ctx(ctx)),
2504 }
2505 }
2506}
2507
2508impl<C: AstFormatter> FmtWithCtx<C> for TypeParam {
2509 fn fmt_with_ctx(&self, _ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2510 write!(f, "{}", self.name)
2511 }
2512}
2513
2514impl<C: AstFormatter> FmtWithCtx<C> for UnOp {
2515 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2516 match self {
2517 UnOp::Not => write!(f, "~"),
2518 UnOp::Neg(mode) => write!(f, "{}.-", mode),
2519 UnOp::Cast(kind) => write!(f, "{}", kind.with_ctx(ctx)),
2520 }
2521 }
2522}
2523
2524impl_display_via_ctx!(Variant);
2525impl<C: AstFormatter> FmtWithCtx<C> for Variant {
2526 fn fmt_with_ctx(&self, ctx: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2527 write!(f, "{}", self.name)?;
2528 if !self.fields.is_empty() {
2529 let fields = self.fields.iter().map(|f| f.with_ctx(ctx)).format(", ");
2530 write!(f, "({})", fields)?;
2531 }
2532 Ok(())
2533 }
2534}