1use std::{
2 fmt::{self, Write},
3 iter,
4};
5
6use expr::{FieldBind, pretty::aggregate_nested};
7use flux_rustc_bridge::ToRustc;
8use rustc_data_structures::snapshot_map::SnapshotMap;
9use rustc_type_ir::DebruijnIndex;
10use ty::{AliasConst, AliasConstKind, ValTree, region_to_string};
11
12use super::{fold::TypeVisitable, *};
13use crate::pretty::*;
14
15impl Pretty for ClauseKind {
16 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 match self {
18 ClauseKind::Trait(pred) => w!(cx, f, "Trait ({:?})", ^pred),
19 ClauseKind::Projection(pred) => w!(cx, f, "Projection ({:?})", ^pred),
20 ClauseKind::RegionOutlives(pred) => {
21 w!(cx, f, "Outlives ({:?}, {:?})", &pred.0, &pred.1)
22 }
23 ClauseKind::TypeOutlives(pred) => w!(cx, f, "Outlives ({:?}, {:?})", &pred.0, &pred.1),
24 ClauseKind::ConstArgHasType(c, ty) => w!(cx, f, "ConstArgHasType ({:?}, {:?})", c, ty),
25 ClauseKind::UnstableFeature(_) => w!(cx, f, "UnstableFeature (..)"),
26 }
27 }
28}
29
30impl Pretty for BoundRegionKind {
31 fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match self {
33 BoundRegionKind::Anon => w!(cx, f, "'<annon>"),
34 BoundRegionKind::NamedForPrinting(sym) => w!(cx, f, "'{sym}"),
35 BoundRegionKind::Named(def_id) => w!(cx, f, "'{def_id:?}"),
36 BoundRegionKind::ClosureEnv => w!(cx, f, "'<env>"),
37 }
38 }
39}
40
41impl<T> Pretty for Binder<T>
42where
43 T: Pretty,
44{
45 default fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 cx.with_bound_vars(self.vars(), || {
47 if !self.vars().is_empty() {
48 cx.fmt_bound_vars(true, "for<", self.vars(), "> ", f)?;
49 }
50 w!(cx, f, "{:?}", self.skip_binder_ref())
51 })
52 }
53}
54
55impl<T: Pretty> std::fmt::Debug for Binder<T> {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 pprint_with_default_cx(f, self, None)
58 }
59}
60
61fn format_fn_root_binder_with<T: TypeVisitable>(
65 binder: &Binder<T>,
66 cx: &PrettyCx,
67 fn_root_layer_type: FnRootLayerType,
68 binder_name: &str,
69 f: &mut fmt::Formatter<'_>,
70 fmt_body: impl FnOnce(&PrettyCx) -> String,
71) -> fmt::Result {
72 let vars = binder.vars();
73 let redundant_bvars = binder.skip_binder_ref().redundant_bvars();
74
75 cx.with_bound_vars_removable(vars, redundant_bvars, Some(fn_root_layer_type), || {
76 let body = fmt_body(cx);
78
79 let filtered_vars = cx.bvar_env.peek_layer().unwrap().filter_vars(vars);
83 if filtered_vars.is_empty() {
84 write!(f, "{}", body)
85 } else {
86 let left = format!("{binder_name}<");
87 let right = format!("> {}", body);
88 cx.fmt_bound_vars(true, &left, &filtered_vars, &right, f)
89 }
90 })
91}
92
93fn format_fn_root_binder<T: Pretty + TypeVisitable>(
94 binder: &Binder<T>,
95 cx: &PrettyCx,
96 fn_root_layer_type: FnRootLayerType,
97 binder_name: &str,
98 f: &mut fmt::Formatter<'_>,
99) -> fmt::Result {
100 format_fn_root_binder_with(binder, cx, fn_root_layer_type, binder_name, f, |cx| {
101 format_cx!(cx, "{:?}", binder.skip_binder_ref())
102 })
103}
104
105impl<T: Pretty> Pretty for EarlyBinder<T> {
106 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 cx.with_early_params(|| self.skip_binder_ref().fmt(cx, f))
108 }
109}
110
111impl Pretty for PolyFnSig {
112 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 format_fn_root_binder(self, cx, FnRootLayerType::FnArgs, "for", f)
114 }
115}
116
117impl Pretty for SortCtor {
118 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 match self {
120 SortCtor::Set => w!(cx, f, "Set"),
121 SortCtor::Map => w!(cx, f, "Map"),
122 SortCtor::User(def_id) => w!(cx, f, "{}", ^def_id.name()),
123 SortCtor::Adt(adt_sort_def) => {
124 w!(cx, f, "{:?}", adt_sort_def.did())
125 }
126 }
127 }
128}
129
130impl Pretty for Sort {
131 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 match self {
133 Sort::Bool => w!(cx, f, "bool"),
134 Sort::Int => w!(cx, f, "int"),
135 Sort::Real => w!(cx, f, "real"),
136 Sort::Str => w!(cx, f, "str"),
137 Sort::Char => w!(cx, f, "char"),
138 Sort::BitVec(size) => w!(cx, f, "bitvec<{:?}>", size),
139 Sort::Loc => w!(cx, f, "loc"),
140 Sort::Var(n) => w!(cx, f, "@{}", ^n.index()),
141 Sort::Func(sort) => w!(cx, f, "{:?}", sort),
142 Sort::Tuple(sorts) => {
143 if let [sort] = &sorts[..] {
144 w!(cx, f, "({:?},)", sort)
145 } else {
146 w!(cx, f, "({:?})", join!(", ", sorts))
147 }
148 }
149 Sort::Alias(alias_ty) => {
150 fmt_alias_ty(cx, f, alias_ty)?;
151 w!(cx, f, "::sort")
152 }
153 Sort::App(ctor, sorts) => {
154 if sorts.is_empty() {
155 w!(cx, f, "{:?}", ctor)
156 } else {
157 w!(cx, f, "{:?}<{:?}>", ctor, join!(", ", sorts))
158 }
159 }
160 Sort::Param(param_ty) => w!(cx, f, "{}::sort", ^param_ty),
161 Sort::Infer(svar) => w!(cx, f, "{:?}", ^svar),
162 Sort::RawPtr => w!(cx, f, "ptr"),
163 Sort::Err => w!(cx, f, "err"),
164 }
165 }
166
167 fn default_cx(tcx: TyCtxt) -> PrettyCx {
168 PrettyCx::default(tcx).hide_refinements(true)
169 }
170}
171
172impl Pretty for SortArg {
173 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 match self {
175 SortArg::Sort(sort) => w!(cx, f, "{:?}", sort),
176 SortArg::BvSize(size) => w!(cx, f, "{:?}", size),
177 }
178 }
179}
180
181impl Pretty for BvSize {
182 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 match self {
184 BvSize::Fixed(size) => w!(cx, f, "{}", ^size),
185 BvSize::Param(param) => w!(cx, f, "{:?}", ^param),
186 BvSize::Infer(size_vid) => w!(cx, f, "{:?}", ^size_vid),
187 }
188 }
189}
190
191impl Pretty for FuncSort {
192 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 match self.inputs() {
194 [input] => {
195 w!(cx, f, "{:?} -> {:?}", input, self.output())
196 }
197 inputs => {
198 w!(cx, f,
199 "({}) -> {:?}",
200 ^inputs
201 .iter()
202 .format_with(", ", |s, f| f(&format_args_cx!(cx, "{:?}", s))),
203 self.output()
204 )
205 }
206 }
207 }
208}
209
210impl Pretty for PolyFuncSort {
211 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212 if self.params.is_empty() {
213 w!(cx, f, "{:?}", &self.fsort)
214 } else {
215 w!(cx, f, "for<{}> {:?}", ^self.params.len(), &self.fsort)
216 }
217 }
218}
219
220impl Pretty for FnSig {
221 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222 w!(
223 cx,
224 f,
225 "fn({:?})",
226 join!(", ", self.inputs.iter().map(|input| input.shallow_canonicalize()))
227 )?;
228 w!(cx, f, " -> ")?;
229 let filtered_requires = self
233 .requires
234 .iter()
235 .filter(|r| !r.is_trivially_true())
236 .collect_vec();
237 let requires_str = if !filtered_requires.is_empty() {
238 format_cx!(cx, " requires {:?}", join!(" && ", &filtered_requires))
239 } else {
240 String::new()
241 };
242 let output = &self.output;
245 format_fn_root_binder_with(output, cx, FnRootLayerType::FnRet, "exists", f, |cx| {
246 let fn_output = output.skip_binder_ref();
247 let mut s = format_cx!(cx, "{:?}", &fn_output.ret.shallow_canonicalize());
248 s.push_str(&requires_str);
249 let filtered_ensures = fn_output
250 .ensures
251 .iter()
252 .filter(|e| {
253 match e {
254 Ensures::Pred(p) => !p.is_trivially_true(),
255 _ => true,
256 }
257 })
258 .collect_vec();
259 if !filtered_ensures.is_empty() {
260 s.push_str(&format_cx!(cx, " ensures {:?}", join!(" && ", &filtered_ensures)));
261 }
262 s
263 })
264 }
265}
266
267impl Pretty for Binder<FnOutput> {
268 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269 format_fn_root_binder(self, cx, FnRootLayerType::FnRet, "exists", f)
270 }
271}
272
273impl Pretty for FnOutput {
274 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
275 w!(cx, f, "{:?}", &self.ret.shallow_canonicalize())?;
276 let filtered_ensures = self
277 .ensures
278 .iter()
279 .filter(|e| {
280 match e {
281 Ensures::Pred(p) => !p.is_trivially_true(),
282 _ => true,
283 }
284 })
285 .collect_vec();
286 if !filtered_ensures.is_empty() {
287 w!(cx, f, " ensures {:?}", join!(" && ", &filtered_ensures))?;
288 }
289 Ok(())
290 }
291}
292
293impl Pretty for Ensures {
294 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 match self {
296 Ensures::Type(loc, ty) => w!(cx, f, "{:?}: {:?}", ^loc, ty),
297 Ensures::Pred(e) => w!(cx, f, "{:?}", e),
298 }
299 }
300}
301
302impl Pretty for SubsetTy {
303 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 w!(cx, f, "{:?}", &self.to_ty())
305 }
306}
307
308struct IdxFmt(Expr);
311
312impl PrettyNested for IdxFmt {
313 fn fmt_nested(&self, cx: &PrettyCx) -> Result<NestedString, fmt::Error> {
314 let kind = self.0.kind();
315 let nested = match kind {
316 ExprKind::Ctor(ctor, flds) => aggregate_nested(cx, ctor, flds, false)?,
317 ExprKind::Tuple(flds) if flds.is_empty() => {
318 NestedString { text: String::new(), key: None, children: None }
319 }
320 ExprKind::Var(Var::Free(name)) => name.fmt_nested(cx)?,
321 _ => self.0.fmt_nested(cx)?,
322 };
323 if nested.text.is_empty() {
325 Ok(nested)
326 } else {
327 Ok(NestedString { text: format!("[{}]", nested.text), ..nested })
328 }
329 }
330}
331
332impl Pretty for IdxFmt {
333 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334 let e = if cx.simplify_exprs {
335 self.0.simplify(&SnapshotMap::default())
336 } else {
337 self.0.clone()
338 };
339 let mut buf = String::new();
340 match e.kind() {
341 ExprKind::Ctor(ctor, flds)
342 if let Some((def_id, _)) = ctor.def_id_and_variant()
343 && let Some(adt_sort_def) = cx.adt_sort_def_of(def_id)
344 && let Some(variant) = adt_sort_def.opt_struct_variant() =>
345 {
346 let fields = iter::zip(variant.field_names(), flds)
347 .map(|(name, value)| FieldBind { name: *name, value: value.clone() })
348 .collect_vec();
349 if let Some(var_fields) = fields
351 .iter()
352 .map(|field| {
353 if let ExprKind::Var(var) = field.value.kind() { Some(*var) } else { None }
354 })
355 .collect::<Option<Vec<_>>>()
356 {
357 if var_fields.iter().all(|var| {
359 if let Var::Bound(debruijn, BoundReft { var, .. }) = var {
360 cx.bvar_env
361 .should_remove_var(*debruijn, *var)
362 .unwrap_or(false)
363 } else {
364 false
365 }
366 }) {
367 var_fields.iter().for_each(|var| {
368 let Var::Bound(debruijn, BoundReft { var, .. }) = var else {
369 unreachable!();
372 };
373 cx.bvar_env.mark_var_as_removed(*debruijn, *var);
374 });
375 } else {
381 let mut fields = var_fields.into_iter().map(|var_e| {
382 match var_e {
383 Var::Bound(debruijn, BoundReft { var, .. })
384 if let Some((seen, layer_type)) =
385 cx.bvar_env.check_if_seen_fn_root_bvar(debruijn, var)
386 && !seen =>
387 {
388 match layer_type {
389 FnRootLayerType::FnArgs => {
390 format_cx!(cx, "@{:?}", var_e)
391 }
392 FnRootLayerType::FnRet => {
393 format_cx!(cx, "#{:?}", var_e)
394 }
395 }
396 }
397 Var::EarlyParam(ep)
398 if cx
399 .earlyparam_env
400 .borrow_mut()
401 .as_mut()
402 .unwrap()
403 .insert(ep) =>
404 {
405 format_cx!(cx, "@{:?}", var_e)
406 }
407 _ => format_cx!(cx, "{:?}", var_e),
408 }
409 });
410 buf.write_str(&fields.join(", "))?;
411 }
412 } else {
413 buf.write_str(&format_cx!(cx, "{{ {:?} }}", join!(", ", fields)))?;
414 }
415 }
416 ExprKind::Var(Var::Bound(debruijn, BoundReft { var, .. })) => {
428 if cx
429 .bvar_env
430 .should_remove_var(*debruijn, *var)
431 .unwrap_or(false)
432 {
433 cx.bvar_env.mark_var_as_removed(*debruijn, *var);
434 } else {
436 if let Some((seen, layer_type)) =
437 cx.bvar_env.check_if_seen_fn_root_bvar(*debruijn, *var)
438 && !seen
439 {
440 match layer_type {
441 FnRootLayerType::FnArgs => {
442 buf.write_str("@")?;
443 }
444 FnRootLayerType::FnRet => {
445 buf.write_str("#")?;
446 }
447 }
448 }
449 buf.write_str(&format_cx!(cx, "{:?}", e))?;
450 }
451 }
452 ExprKind::Var(Var::EarlyParam(ep)) => {
453 if let Some(param) = cx.earlyparam_env.borrow_mut().as_mut()
454 && param.insert(*ep)
455 {
456 buf.write_str(&format_cx!(cx, "@{:?}", e))?;
458 } else {
459 buf.write_str(&format_cx!(cx, "{:?}", e))?;
460 }
461 }
462 _ => {
463 buf.write_str(&format_cx!(cx, "{:?}", e))?;
464 }
465 }
466 if !buf.is_empty() { write!(f, "[{}]", buf) } else { Ok(()) }
467 }
468}
469
470impl Pretty for Ty {
471 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472 match self.kind() {
473 TyKind::Indexed(bty, idx) => {
474 if cx.hide_refinements {
475 w!(cx, f, "{:?}", bty)?;
476 return Ok(());
477 }
478 if idx.is_unit() {
479 w!(cx, f, "{:?}", bty)?;
480 } else {
481 w!(cx, f, "{:?}{:?}", parens!(bty, !bty.is_atom()), IdxFmt(idx.clone()))?;
482 }
483 Ok(())
484 }
485 TyKind::Exists(_ty_ctor) => {
486 w!(cx, f, "{:?}", self.shallow_canonicalize())
487 }
488 TyKind::Uninit => w!(cx, f, "uninit"),
489 TyKind::StrgRef(re, loc, ty) => {
490 if cx.hide_regions {
491 w!(cx, f, "{:?}: &strg {:?}", loc, ty)
492 } else {
493 w!(cx, f, "{:?}: &{:?} strg {:?}", loc, re, ty)
494 }
495 }
496 TyKind::Ptr(pk, loc) => w!(cx, f, "ptr({:?}, {:?})", pk, loc),
497 TyKind::Discr(adt_def, place) => {
498 w!(cx, f, "discr({:?}, {:?})", adt_def.did(), ^place)
499 }
500 TyKind::Constr(pred, ty) => {
501 if cx.hide_refinements {
502 w!(cx, f, "{:?}", ty)
503 } else {
504 w!(cx, f, "{{ {:?} | {:?} }}", ty, pred.clone())
505 }
506 }
507 TyKind::Param(param_ty) => w!(cx, f, "{}", ^param_ty),
508 TyKind::Downcast(adt, .., variant_idx, fields) => {
509 w!(cx, f, "{:?}", adt.did())?;
511 if !adt.is_struct() {
513 w!(cx, f, "::{}", ^adt.variant(*variant_idx).name)?;
514 }
515 if adt.is_struct() {
517 let field_binds = iter::zip(&adt.variant(*variant_idx).fields, fields)
518 .map(|(field_def, value)| FieldBind { name: field_def.name, value });
519 w!(cx, f, " {{ {:?} }}", join!(", ", field_binds))?;
520 } else if !fields.is_empty() {
521 w!(cx, f, "({:?})", join!(", ", fields))?;
522 }
523 Ok(())
524 }
525 TyKind::Blocked(ty) => w!(cx, f, "†{:?}", ty),
526 TyKind::Infer(ty_vid) => {
527 w!(cx, f, "{ty_vid:?}")
528 }
529 }
530 }
531
532 fn default_cx(tcx: TyCtxt) -> PrettyCx {
533 PrettyCx::default(tcx).kvar_args(KVarArgs::Hide)
534 }
535}
536
537impl Pretty for PtrKind {
538 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539 match self {
540 PtrKind::Mut(re) => {
541 w!(cx, f, "mut")?;
542 if !cx.hide_regions {
543 w!(cx, f, "[{:?}]", re)?;
544 }
545 Ok(())
546 }
547 PtrKind::Box => w!(cx, f, "box"),
548 }
549 }
550}
551
552impl Pretty for List<Ty> {
553 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
554 if let [ty] = &self[..] {
555 w!(cx, f, "({:?},)", ty)
556 } else {
557 w!(cx, f, "({:?})", join!(", ", self))
558 }
559 }
560}
561
562impl Pretty for ExistentialPredicate {
563 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
564 match self {
565 ExistentialPredicate::Trait(trait_ref) => w!(cx, f, "{:?}", trait_ref),
566 ExistentialPredicate::Projection(proj) => w!(cx, f, "({:?})", proj),
567 ExistentialPredicate::AutoTrait(def_id) => w!(cx, f, "{:?}", def_id),
568 }
569 }
570}
571
572impl Pretty for ExistentialTraitRef {
573 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
574 w!(cx, f, "{:?}", self.def_id)?;
575 if !self.args.is_empty() {
576 w!(cx, f, "<{:?}>", join!(", ", &self.args))?;
577 }
578 Ok(())
579 }
580}
581
582impl Pretty for ExistentialProjection {
583 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584 w!(cx, f, "{:?}", self.def_id)?;
585 if !self.args.is_empty() {
586 w!(cx, f, "<{:?}>", join!(", ", &self.args))?;
587 }
588 w!(cx, f, " = {:?}", &self.term)
589 }
590}
591
592impl Pretty for BaseTy {
593 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
594 match self {
595 BaseTy::Int(int_ty) => w!(cx, f, "{}", ^int_ty.name_str()),
596 BaseTy::Uint(uint_ty) => w!(cx, f, "{}", ^uint_ty.name_str()),
597 BaseTy::Bool => w!(cx, f, "bool"),
598 BaseTy::Str => w!(cx, f, "str"),
599 BaseTy::Char => w!(cx, f, "char"),
600 BaseTy::Adt(adt_def, args) => {
601 w!(cx, f, "{:?}", adt_def.did())?;
602 let mut args: Vec<_> = args
603 .iter()
604 .filter(|arg| !cx.hide_regions || !matches!(arg, GenericArg::Lifetime(_)))
605 .collect();
606 if cx.hide_default_args {
607 let tcx = cx.tcx();
608 let generics = tcx.generics_of(adt_def.did());
609 while let Some(arg) = args.last() {
611 let arg_idx = args.len() - 1;
612 if arg_idx >= generics.own_params.len() {
613 break;
614 }
615 let param = &generics.own_params[arg_idx];
616 let has_default = match param.kind {
617 rustc_middle::ty::GenericParamDefKind::Type { has_default, .. } => {
618 has_default
619 }
620 rustc_middle::ty::GenericParamDefKind::Const {
621 has_default, ..
622 } => has_default,
623 _ => false,
624 };
625 if !has_default {
626 break;
627 }
628 let earlier_args =
629 tcx.mk_args_from_iter(args[..arg_idx].iter().map(|a| a.to_rustc(tcx)));
630 let default_ty = tcx
631 .type_of(param.def_id)
632 .instantiate(tcx, earlier_args)
633 .skip_norm_wip();
634 if arg.to_rustc(tcx) != rustc_middle::ty::GenericArg::from(default_ty) {
635 break;
636 }
637 args.pop();
638 }
639 }
640 if !args.is_empty() {
641 w!(cx, f, "<{:?}>", join!(", ", args))?;
642 }
643 Ok(())
644 }
645 BaseTy::FnDef(def_id, args) => {
646 w!(cx, f, "FnDef({:?}[{:?}])", def_id, join!(", ", args))
647 }
648 BaseTy::Param(param) => w!(cx, f, "{}", ^param),
649 BaseTy::Float(float_ty) => w!(cx, f, "{}", ^float_ty.name_str()),
650 BaseTy::Slice(ty) => w!(cx, f, "[{:?}]", ty),
651 BaseTy::RawPtr(ty, Mutability::Mut) => w!(cx, f, "*mut {:?}", ty),
652 BaseTy::RawPtr(ty, Mutability::Not) => w!(cx, f, "*const {:?}", ty),
653 BaseTy::RawPtrMetadata(ty) => {
654 w!(cx, f, "*raw {:?}", ty)
655 }
656 BaseTy::Ref(re, ty, mutbl) => {
657 w!(cx, f, "&")?;
658 if !cx.hide_regions {
659 w!(cx, f, "{:?} ", re)?;
660 }
661 w!(cx, f, "{}{:?}", ^mutbl.prefix_str(), ty)
662 }
663 BaseTy::FnPtr(poly_fn_sig) => {
664 w!(cx, f, "{:?}", poly_fn_sig)
665 }
666 BaseTy::Tuple(tys) => {
667 if let [ty] = &tys[..] {
668 w!(cx, f, "({:?},)", ty)
669 } else {
670 w!(cx, f, "({:?})", join!(", ", tys))
671 }
672 }
673 BaseTy::Alias(alias_ty) => fmt_alias_ty(cx, f, alias_ty),
674 BaseTy::Array(ty, c) => w!(cx, f, "[{:?}; {:?}]", ty, ^c),
675 BaseTy::Never => w!(cx, f, "!"),
676 BaseTy::Closure(did, args, _, _) => {
677 w!(cx, f, "{:?}<{:?}>", did, args)
678 }
679 BaseTy::Coroutine(did, resume_ty, upvars, _) => {
680 w!(cx, f, "Coroutine({:?}, {:?})", did, resume_ty)?;
681 if !upvars.is_empty() {
682 w!(cx, f, "<{:?}>", join!(", ", upvars))?;
683 }
684 Ok(())
685 }
686 BaseTy::Dynamic(preds, re) => {
687 w!(cx, f, "dyn {:?} + {:?}", join!(" + ", preds), re)
688 }
689 BaseTy::Infer(ty_vid) => {
690 w!(cx, f, "{ty_vid:?}")
691 }
692 BaseTy::Foreign(def_id) => {
693 w!(cx, f, "{:?}", def_id)
694 }
695 BaseTy::Pat => todo!(),
696 }
697 }
698}
699
700fn fmt_alias_ty(cx: &PrettyCx, f: &mut fmt::Formatter<'_>, alias_ty: &AliasTy) -> fmt::Result {
701 match alias_ty.kind {
702 AliasKind::Free { def_id } => {
703 w!(cx, f, "{:?}", def_id)?;
704 if !alias_ty.args.is_empty() {
705 w!(cx, f, "<{:?}>", join!(", ", &alias_ty.args))?;
706 }
707 }
708 AliasKind::Projection { def_id } => {
709 let assoc_name = cx.tcx().item_name(def_id);
710 let trait_ref = cx.tcx().parent(def_id);
711 let trait_generic_count = cx.tcx().generics_of(trait_ref).count() - 1;
712
713 let [self_ty, args @ ..] = &alias_ty.args[..] else {
714 return w!(cx, f, "<alias_ty>");
715 };
716
717 w!(cx, f, "<{:?} as {:?}", self_ty, trait_ref)?;
718
719 let trait_generics = &args[..trait_generic_count];
720 if !trait_generics.is_empty() {
721 w!(cx, f, "<{:?}>", join!(", ", trait_generics))?;
722 }
723 w!(cx, f, ">::{}", ^assoc_name)?;
724
725 let assoc_generics = &args[trait_generic_count..];
726 if !assoc_generics.is_empty() {
727 w!(cx, f, "<{:?}>", join!(", ", assoc_generics))?;
728 }
729 }
730 AliasKind::Opaque { def_id } => {
731 w!(cx, f, "{:?}", def_id)?;
732 if !alias_ty.args.is_empty() {
733 w!(cx, f, "<{:?}>", join!(", ", &alias_ty.args))?;
734 }
735 if !alias_ty.refine_args.is_empty() {
736 w!(cx, f, "⟨{:?}⟩", join!(", ", &alias_ty.refine_args))?;
737 }
738 }
739 }
740 Ok(())
741}
742
743impl Pretty for ValTree {
744 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
745 match self {
746 ValTree::Leaf(v) => w!(cx, f, "Leaf({v:?})"),
747 ValTree::Branch(children) => {
748 w!(cx, f, "Branch([{:?}])", join!(", ", children))
749 }
750 }
751 }
752}
753impl Pretty for AliasConst {
754 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
755 let (descr, def_id) = match self.kind {
756 AliasConstKind::Projection { def_id } => ("projection", def_id),
757 AliasConstKind::Inherent { def_id } => ("inherent", def_id),
758 AliasConstKind::Free { def_id } => ("free", def_id),
759 AliasConstKind::Anon { def_id } => ("anon", def_id),
760 };
761 w!(cx, f, "AliasConst({} {:?}[...])", ^descr, def_id)
762 }
763}
764
765impl Pretty for Const {
766 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
767 match &self.kind {
768 ConstKind::Param(p) => w!(cx, f, "{}", ^p.name.as_str()),
769 ConstKind::Value(_, v) => w!(cx, f, "{v:?}"),
770 ConstKind::Infer(infer_const) => w!(cx, f, "{:?}", ^infer_const),
771 ConstKind::Alias(uneval_const) => w!(cx, f, "{:?}", uneval_const),
772 }
773 }
774}
775
776impl Pretty for GenericArg {
777 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
778 match self {
779 GenericArg::Ty(ty) => w!(cx, f, "{:?}", ty),
780 GenericArg::Base(ctor) => w!(cx, f, "{:?}", ctor.to_ty()),
781 GenericArg::Lifetime(re) => w!(cx, f, "{:?}", re),
782 GenericArg::Const(c) => w!(cx, f, "{:?}", c),
783 }
784 }
785}
786
787impl Pretty for VariantSig {
788 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
789 w!(cx, f, "({:?}) => {:?}", join!(", ", self.fields()), &self.idx)
790 }
791}
792
793impl Pretty for Region {
794 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
795 w!(cx, f, "{}", ^region_to_string(*self))
796 }
797}
798
799impl Pretty for DebruijnIndex {
800 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
801 w!(cx, f, "^{}", ^self.as_usize())
802 }
803}
804
805impl_debug_with_default_cx!(
806 Ensures,
807 Sort,
808 Ty => "ty",
809 BaseTy,
810 FnSig,
811 GenericArg => "generic_arg",
812 VariantSig,
813 PtrKind,
814 FuncSort,
815 SortCtor,
816 SubsetTy,
817 BvSize,
818 ExistentialPredicate,
819);
820
821impl PrettyNested for SubsetTy {
822 fn fmt_nested(&self, cx: &PrettyCx) -> Result<NestedString, fmt::Error> {
823 let bty_d = self.bty.fmt_nested(cx)?;
824 let idx_d = IdxFmt(self.idx.clone()).fmt_nested(cx)?;
825 if self.pred.is_trivially_true() || matches!(self.pred.kind(), ExprKind::KVar(..)) {
826 let text = format!("{}{}", bty_d.text, idx_d.text);
827 let children = float_children(vec![bty_d.children, idx_d.children]);
828 Ok(NestedString { text, children, key: None })
829 } else {
830 let pred_d = self.pred.fmt_nested(cx)?;
831 let text = format!("{{ {}{} | {} }}", bty_d.text, idx_d.text, pred_d.text);
832 let children = float_children(vec![bty_d.children, idx_d.children, pred_d.children]);
833 Ok(NestedString { text, children, key: None })
834 }
835 }
836}
837
838impl PrettyNested for GenericArg {
839 fn fmt_nested(&self, cx: &PrettyCx) -> Result<NestedString, fmt::Error> {
840 match self {
841 GenericArg::Ty(ty) => ty.fmt_nested(cx),
842 GenericArg::Base(ctor) => {
843 let inner = ctor.as_ref().skip_binder();
845 if ctor.vars().len() == 1 && inner.pred.is_trivially_true() && inner.idx.is_nu() {
846 inner.bty.fmt_nested(cx)
847 } else {
848 cx.nested_with_bound_vars("λ", ctor.vars(), None, |prefix| {
849 let ctor_d = ctor.skip_binder_ref().fmt_nested(cx)?;
850 let text = format!("{}{}", prefix, ctor_d.text);
851 Ok(NestedString { text, children: ctor_d.children, key: None })
852 })
853 }
854 }
855 GenericArg::Lifetime(..) | GenericArg::Const(..) => debug_nested(cx, self),
856 }
857 }
858}
859
860impl PrettyNested for BaseTy {
861 fn fmt_nested(&self, cx: &PrettyCx) -> Result<NestedString, fmt::Error> {
862 match self {
863 BaseTy::Int(..)
864 | BaseTy::Uint(..)
865 | BaseTy::Bool
866 | BaseTy::Str
867 | BaseTy::Char
868 | BaseTy::Float(..)
869 | BaseTy::Param(..)
870 | BaseTy::Never
871 | BaseTy::FnPtr(..)
872 | BaseTy::FnDef(..)
873 | BaseTy::Alias(..)
874 | BaseTy::Closure(..)
875 | BaseTy::Coroutine(..)
876 | BaseTy::Dynamic(..)
877 | BaseTy::Infer(..)
878 | BaseTy::Foreign(..) => {
879 let text = format_cx!(cx, "{:?}", self);
880 Ok(NestedString { text, children: None, key: None })
881 }
882 BaseTy::Slice(ty) => {
883 let ty_d = ty.fmt_nested(cx)?;
884 let text = format!("[{}]", ty_d.text);
885 Ok(NestedString { text, children: ty_d.children, key: None })
886 }
887 BaseTy::Array(ty, c) => {
888 let ty_d = ty.fmt_nested(cx)?;
889 let text = format_cx!(cx, "[{:?}; {:?}]", ty_d.text, c);
890 Ok(NestedString { text, children: ty_d.children, key: None })
891 }
892 BaseTy::RawPtr(ty, Mutability::Mut) => {
893 let ty_d = ty.fmt_nested(cx)?;
894 let text = format!("*mut {}", ty_d.text);
895 Ok(NestedString { text, children: ty_d.children, key: None })
896 }
897 BaseTy::RawPtr(ty, Mutability::Not) => {
898 let ty_d = ty.fmt_nested(cx)?;
899 let text = format!("*const {}", ty_d.text);
900 Ok(NestedString { text, children: ty_d.children, key: None })
901 }
902 BaseTy::RawPtrMetadata(ty) => {
903 let ty_d = ty.fmt_nested(cx)?;
904 let text = format!("*raw {}", ty_d.text);
905 Ok(NestedString { text, children: ty_d.children, key: None })
906 }
907 BaseTy::Ref(_, ty, mutbl) => {
908 let ty_d = ty.fmt_nested(cx)?;
909 let prefix = mutbl.prefix_str();
910 let text = if prefix.is_empty() {
911 format!("&{}", ty_d.text)
912 } else {
913 format!("&{} {}", prefix, ty_d.text)
914 };
915 Ok(NestedString { text, children: ty_d.children, key: None })
916 }
917 BaseTy::Tuple(tys) => {
918 let mut texts = vec![];
919 let mut kidss = vec![];
920 for ty in tys {
921 let ty_d = ty.fmt_nested(cx)?;
922 texts.push(ty_d.text);
923 kidss.push(ty_d.children);
924 }
925 let text = if let [text] = &texts[..] {
926 format!("({text},)")
927 } else {
928 format!("({})", texts.join(", "))
929 };
930 let children = float_children(kidss);
931 Ok(NestedString { text, children, key: None })
932 }
933 BaseTy::Adt(adt_def, args) => {
934 let mut texts = vec![];
935 let mut kidss = vec![];
936 for arg in args {
937 let arg_d = arg.fmt_nested(cx)?;
938 texts.push(arg_d.text);
939 kidss.push(arg_d.children);
940 }
941 let args_str = if !args.is_empty() {
942 format!("<{}>", texts.join(", "))
943 } else {
944 String::new()
945 };
946 let text = format_cx!(cx, "{:?}{:?}", adt_def.did(), args_str);
947 let children = float_children(kidss);
948 Ok(NestedString { text, children, key: None })
949 }
950 BaseTy::Pat => todo!(),
951 }
952 }
953}
954
955impl PrettyNested for Ty {
956 fn fmt_nested(&self, cx: &PrettyCx) -> Result<NestedString, fmt::Error> {
957 match self.kind() {
958 TyKind::Indexed(bty, idx) => {
959 let bty_d = bty.fmt_nested(cx)?;
960 let idx_d = IdxFmt(idx.clone()).fmt_nested(cx)?;
961 let text = if idx_d.text.is_empty() {
962 bty_d.text
963 } else {
964 format!("{}{}", bty_d.text, idx_d.text)
965 };
966 let children = float_children(vec![bty_d.children, idx_d.children]);
967 Ok(NestedString { text, children, key: None })
968 }
969 TyKind::Exists(ty_ctor) => {
970 if ty_ctor.vars().len() == 1
973 && let TyKind::Indexed(bty, idx) = ty_ctor.skip_binder_ref().kind()
974 && idx.is_nu()
975 {
976 bty.fmt_nested(cx)
977 } else {
978 cx.nested_with_bound_vars("∃", ty_ctor.vars(), None, |exi_str| {
979 let ty_ctor_d = ty_ctor.skip_binder_ref().fmt_nested(cx)?;
980 let text = format!("{}{}", exi_str, ty_ctor_d.text);
981 Ok(NestedString { text, children: ty_ctor_d.children, key: None })
982 })
983 }
984 }
985 TyKind::Constr(expr, ty) => {
986 let expr_d = expr.fmt_nested(cx)?;
987 let ty_d = ty.fmt_nested(cx)?;
988 let text = format!("{{ {} | {} }}", ty_d.text, expr_d.text);
989 let children = float_children(vec![expr_d.children, ty_d.children]);
990 Ok(NestedString { text, children, key: None })
991 }
992 TyKind::StrgRef(re, loc, ty) => {
993 let ty_d = ty.fmt_nested(cx)?;
994 let text = if cx.hide_regions {
995 format!("{:?}: &strg {}", loc, ty_d.text)
996 } else {
997 format!("{:?}: &{:?} strg {}", loc, re, ty_d.text)
998 };
999 Ok(NestedString { text, children: ty_d.children, key: None })
1000 }
1001 TyKind::Blocked(ty) => {
1002 let ty_d = ty.fmt_nested(cx)?;
1003 let text = format!("†{}", ty_d.text);
1004 Ok(NestedString { text, children: ty_d.children, key: None })
1005 }
1006 TyKind::Downcast(adt, .., variant_idx, fields) => {
1007 let is_struct = adt.is_struct();
1008 let mut text = format_cx!(cx, "{:?}", adt.did());
1009 if !is_struct {
1010 text.push_str(&format!("::{}", adt.variant(*variant_idx).name));
1011 }
1012 if is_struct {
1013 text.push_str("{..}");
1014 } else {
1015 text.push_str("(..)");
1016 }
1017 let keys: Vec<String> = if is_struct {
1018 adt.variant(*variant_idx)
1019 .fields
1020 .iter()
1021 .map(|f| f.name.to_string())
1022 .collect()
1023 } else {
1024 (0..fields.len()).map(|i| format!("{i}")).collect()
1025 };
1026 let mut children = vec![];
1027 for (key, field) in keys.into_iter().zip(fields) {
1028 let field_d = field.fmt_nested(cx)?;
1029 children.push(NestedString { key: Some(key), ..field_d });
1030 }
1031 Ok(NestedString { text, children: Some(children), key: None })
1032 }
1033 TyKind::Param(..)
1034 | TyKind::Uninit
1035 | TyKind::Ptr(..)
1036 | TyKind::Discr(..)
1037 | TyKind::Infer(..) => {
1038 let text = format!("{self:?}");
1039 Ok(NestedString { text, children: None, key: None })
1040 }
1041 }
1042 }
1043}