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